在Python中使用ctypes的回调中的c_void_p参数

时间:2014-04-24 12:05:51

标签: python callback ctypes

我经常使用ctypes,但我遇到了一些我无法解释的事情。

首先,当我使用c_void_p定义回调时,回调将收到一个扁平整数。

我看到一些其他帖子提到在使用c_void_p作为返回值时,在另一个POINTER中包装c_void_p。所以,我认为我可以在回调定义中为参数尝试这个:POINTER(c_void_p)。现在,我在调用回调时得到一个指针,但我仍然不知道它是否指向值数据。

由于C_void_p指向具有二进制数据的缓冲区,我不相信我可以使用c_char_p。我投射到一个无符号字符数组,其长度与我相同,但是Python告诉我,我有一个元组,并且没有"内容"或"价值"我可以使用的财产。

建议?

1 个答案:

答案 0 :(得分:6)

在回调中接收c_void_p作为整数是正常的。它使用简单类型getfunc进行自动转换 - 与将c_void_p作为Structure字段相同。 ctypes不会为简单类型的子类进行自动转换 - 例如type('my_void_p', (c_void_p,), {})。虽然我认为在这种情况下并不重要。

假设您在p中有一个整数地址。您可以使用以下任一 * 将其强制转换为c_char长度为n的数组:

buf = cast(p, POINTER(c_char * n))[0]

# 2.6+
buf = (c_char * n).from_address(p)

那就是说,知道它是char *,我会定义回调以使用POINTER(c_char)。然后通过索引或切片访问缓冲区,例如p[0]p[:n]


* p[n]等同于*(p + n),其中*是解引用运算符,并且添加使用基于指示对象大小的指针算法。您可以使用p.contents代替p[0],但后者也会调用类型的getfunc转换器(如果适用)。