I'm writing Python bindings for a C library that heavily uses callbacks. For convenience in Python, I'm searching for a way to pass a Python object as void *
to the C function, and once it gives the pointer back to me in the Python callback, convert it back to the Python object.
First, here is an example C file:
test1.c
void call_callback(void (*callback)(void *), void *user_data)
{
callback(user_data);
}
Compile this to a shared library named libtest1.so
. Here is an example Python file:
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))
So, far everything works ok. Data to be sent can be created with ctypes.c_int
for example and sent by ctypes.byref
, and later recovered by a ctypes.cast
to the appropriate type (ctypes.POINTER(ctypes.c_int)
).
My question is the following. Is it possible for me to give any normal Python object as a ctypes.c_void_p
when calling a C function? If so, how? Also, how can I recover the Python object when I get that pointer back in a Python callback?
Imagine the following code:
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))
I am essentially looking for the convert_to_c_void_p
and c_void_p_was_really_a_python_X
functions.
A solution that works both with Python 2 (>= 2.7) and Python 3 would be great, but I would be interested in version specific answers as well.