Receiving a c_void_p
as an integer in the callback is normal. It's using the simple type's getfunc
to do the automatic conversion -- same as getting a c_void_p
as a Structure
field. ctypes won't do automatic conversion for a subclass of a simple type -- e.g. type('my_void_p', (c_void_p,), {})
. Though I don't think that matters in this case.
Say you have an integer address in p
. You can cast it to a c_char
array of length n
using either of the following*:
buf = cast(p, POINTER(c_char * n))[0]
# 2.6+
buf = (c_char * n).from_address(p)
That said, knowing that it's a char *
, I'd define the callback to use POINTER(c_char)
. Then access the buffer by index or a slice, e.g. p[0]
or p[:n]
.
*p[n]
is equivalent to *(p + n)
, where *
is the dereference operator and the addition is using pointer arithmetic based on the size of the referent. You can use p.contents
instead of p[0]
, but the latter also calls the type's getfunc
converter, if applicable.