Использование ctypes для взаимодействия моего python3 кода с C API. Одна из функций C регистрирует функцию обратного вызова, т. Е. Она принимает указатель функции на обратный вызов и void* userdata
, который должен быть доступен в этом обратном вызове.
// typedef and C function in myClibrary.so
typedef void(__cdecl *callback_function_type)(void*);
int RegCallback(callback_function_type callback_function, void* userbdata);
Я успешно определил требуемый обратный вызов наберите в python функцию, используя CFUNCTYPE()
, передайте ее экземпляр функции C и убедитесь, что моя функция обратного вызова выполняется при желании.
Я также успешно отправил простой тип (т.е. int
) как userdata
и доступ к нему в обратном вызове. Однако отправка сложных типов (то есть пользовательских классов) ускользает от меня.
Мне нужна помощь, чтобы понять, как 1) привести мой объект self
к c_void_p
(как аргумент userdata
), а затем 2) восстановить или вернуть аргумент userdata
, доступный в обратном вызове, к исходному типу self
для использования в обратном вызове. (Как и в C ++, что можно сделать, приведя указатель this
объекта к void*
и затем приведя обратно к его исходному типу в обратном вызове.)
Может кто-нибудь помочь мне получить правильный синтаксис для " связать "self
как c_void_p
и затем" разделить "обратно до его типа класса в обратном вызове?
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
Эти связанные вопросы близки, но не совсем получить ответ, который я специально ищу с помощью объекта self
. Общая рекомендация, похоже, заключается в том, чтобы использовать лямбда-захват вместо c_void_p
, но я тоже не могу этого понять.
Пропустить Python объект через void * и вернуться обратно обратный вызов
Python объекты в качестве пользовательских данных в функциях обратного вызова ctypes