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?
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'))
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.
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?
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'))
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 acreate_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.