我正在为大量使用回调的C库编写Python绑定。为了方便Python,我正在寻找一种将Python对象作为void *
传递给C函数的方法,并且一旦它在Python回调中将指针返回给我,就将其转换回Python对象
首先,这是一个示例C文件:
test1.c
void call_callback(void (*callback)(void *), void *user_data)
{
callback(user_data);
}
将其编译为名为libtest1.so
的共享库。这是一个示例Python文件:
test1.py
# Create bindings (in reality done in a module)
from ctypes import *
cdll.LoadLibrary("libtest1.so")
test1 = CDLL("libtest1.so")
test1.call_callback.argtypes = [CFUNCTYPE(None, c_void_p), c_void_p]
test1.call_callback.restype = None
def call_callback(func, data):
# Note: converting Python function to be callable from C
callback = CFUNCTYPE(None, c_void_p)(func)
test1.call_callback(callback, data)
# Testing:
def callback1(data):
number = cast(data, POINTER(c_int))
print('Callback 1 got:', number[0])
data1 = c_int(10)
call_callback(callback1, byref(data1))
所以,一切都运转正常。要发送的数据可以使用ctypes.c_int
创建,并由ctypes.byref
发送,然后由ctypes.cast
恢复为相应的类型(ctypes.POINTER(ctypes.c_int)
)。
我的问题如下。在调用C函数时,我可以将任何普通的Python对象作为ctypes.c_void_p
吗?如果是这样,怎么样?另外,当我在Python回调中获得指针时,如何恢复Python对象?
想象一下以下代码:
def callback2(data):
list = c_void_p_was_really_a_python_list(data)
print('callback 2 got:', list)
data2 = [1, 2, 3]
call_callback(callback2, convert_to_c_void_p(data2))
我基本上在寻找convert_to_c_void_p
和c_void_p_was_really_a_python_X
函数。
兼容Python 2(> = 2.7)和Python 3的解决方案会很棒,但我也会对版本特定的答案感兴趣。