4

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?

1 Answer 1

7

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, @eryksun. I guess what I needed was the [0]. Why does the cast return a tuple? It's not documented for the cast in the ctypes documentation: docs.python.org/2/library/ctypes.html#ctypes.cast
I don't understand why you're getting a list/enumerable of one when you do a cast to an N-size array, and why you should have to do [0]. Is the [0] the "dereference" that you're referring to?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.