Can I pass a Python “self” object to a C function as c_void_p and cast to original type for use in a callback?

爷,独闯天下 提交于 2021-02-11 06:16:41

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!