ctypes character pointers with same byte string points same location

Question:

I am creating two ctypes character pointers with same byte string via:

import ctypes as ct

var1 = ct.c_char_p(b'.'*80)
var2 = ct.c_char_p(b'.'*80)

# how I check the values:
api = ct.CDLL('api.dll')
api.function1(var1, var2)

# values of the vars are changed after running the above function
print(var1.value.decode(), var2.value.decode())

I am running a CDLL.function which changes values in the locations where var1 and var2 points. I was expecting, that if I would create 2 different pointers like above, these pointers would point a different location in memory. However, they do point to the same location, because when I check the values of these variables they are the same.

When I create the var2 with different character (e.g.: b'*'80) instead of b'.'*80, then it works. Is there a better way to create var1 and var2, so that both of these pointers would point a different location?

Asked By: oakca

||

Answers:

I found a way, but I am also open for suggestions. Creating both variables with this way works:

var1 = ct.c_char_p(bytes('.' * 80, encoding='utf-8'))
var2 = ct.c_char_p(bytes('.' * 80, encoding='utf-8'))
Answered By: oakca

b'.'*80 is an immutable string and Python (as an implementation detail) is completely free to re-use the object and give you the same pointer for both var1 and var2. If your C function is changing it, that is undefined behavior.

Instead, use ctypes.create_string_buffer(b'.'*80) to create a writable buffer.

Quote from the documentation:

You should be careful, however, not to pass [c_char_p] to functions expecting pointers to mutable memory. If you need mutable memory blocks, ctypes has a create_string_buffer() function which creates these in various ways. The current memory block contents can be accessed (or changed) with the raw property; if you want to access it as NUL terminated string, use the value property.

Answered By: Mark Tolonen