问题
Using ctypes to interface my python3 code with a C API. One of the C functions registers a callback function– i.e. it takes a function pointer to the callback and a void* userdata
to be made available in that callback.
// typedef and C function in myClibrary.so
typedef void(__cdecl *callback_function_type)(void*);
int RegCallback(callback_function_type callback_function, void* userbdata);
I have successfully defined the required callback function type in python using CFUNCTYPE()
, passed an instance of it to the C function, and verified that my callback function is executed when desired.
I have also successfully sent a simple type (i.e. int
) as the userdata
and accessed it in the callback. However, sending complex types (i.e. custom classes) eludes me.
I need help figuring out how to 1) cast my self
object to a c_void_p
(as the userdata
argument), and then 2) recover or cast back the userdata
argument available in the callback to self
's original type for use in the callback. (As in C++ which would be done by casting an object's this
pointer to a void*
and then casting back to its original type in the callback.)
Can someone help me get the correct syntax for "bundling up" self
as a c_void_p
and then "unbundling" back to its class type in the callback?
from ctypes import *
myClibrary = CDLL("myClibrary.so")
callback_t = CFUNCTYPE(None, c_void_p) # define type of callback function
RegisterCallback = myClibrary.RegCallback # RegCallback is a C library function
RegisterCallback.argtypes = [callback_t, c_void_p] # define its argument types
RegisterCallback.restype = c_int # define its result type
# define my callback function
def callback_fn(pArg):
print('Hello from the callback function!')
# I NEED TO BE ABLE TO ACCESS pArg as an instance of myClass type here in the callback
# construct global instance of the callback function which can be passed as argument to RegisterCallback
_callback_fn = callback_t(callback_fn)
# define custom class, instance of which needs to be passed to callback function
class myClass
def __init__(self):
userdata = c_void_p.from_buffer(py_object(self)). # I think this is correct, but maybe not?
retval = RegisterCallback(_callback_fn, userdata). # register the callback function
These related questions are close but don't quite get to the answer I'm specifically looking for with the self
object. The general recommendation seems to be to use a lambda capture instead of a c_void_p
, but I can't quite figure that out either.
Pass Python object through void * and get back in callback
Python objects as userdata in ctypes callback functions
来源:https://stackoverflow.com/questions/60219216/can-i-pass-a-python-self-object-to-a-c-function-as-c-void-p-and-cast-to-origin