Вопрос

I'm a frequent user of ctypes, but I encountered some things that I can't explain.

First, when I define a callback with a c_void_p, the callback will receive a flat integer.

I saw some other posts that mentioned wrapping c_void_p in another POINTER when it came to using c_void_p for a return value. So, I thought that I could try this for the argument in the callback definition: POINTER(c_void_p). I get a pointer when the callback is called, now, but I still don't know whether it points to value data.

Since the C_void_p points to a buffer with binary data, I don't believe that I can use a c_char_p. I cast to an array of unsigned-chars with the length that I am being passed, but then Python tells me that I have a tuple, and there's no "contents" or "value" property that I can use.

Suggestions?

Это было полезно?

Решение

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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top