У меня есть C api, что я взаимодействую с пакетом ctypes python. Все работает хорошо, кроме этого небольшого лакомого кусочка.
Чтобы зарегистрировать функции как обратные вызовы для некоторых уведомлений, я вызываю эту функцию:
void RegisterNotifyCallback( int loginId, int extraFlags, void *(*callbackFunc)(Notification *))
поэтому в python мой код выглядит следующим образом:
CALLBACK = ctypes.CFUNCTYPE(None, ctypes.POINTER(Notification))
func = CALLBACK(myPythonCallback)
myLib.RegisterNofityCallback(45454, 0, func)
Если значение myPythonCallback является FunctionType (т.е. не методом), оно отлично работает и вызывает функцию обратного вызова с правильными параметрами. Если это MethodType, он по-прежнему вызывает этот метод, но затем взрывается с segfault после завершения метода.
изменить
Чтобы уточнить, когда я говорю, что тип функции я означает, что myPythonCallback определяется как функция,
def myPythonCallback(Notification):
...do something with the Notification object i get passed in
Когда я говорю это MethodType, я имею в виду метод класса:
class MyClass(object):
def myPythonCallback(self, Notification):
...do something with Notification
Взорвается второй тип.
Легко ли это? Или может кто-нибудь предложить мне объяснение, почему это происходит?
Большое спасибо, Ал.
изменить
Копаем немного больше с помощью GDB, это дает мне следующее:
Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 1544567712 (LWP 5389)] 0x555ae962 in instancemethod_dealloc (im=0x558ed644) at Objects/classobject.c:2360 2360 Objects/classobject.c: No such file or directory.
in Objects/classobject.c (gdb) backtrace
#0 0x555ae962 in instancemethod_dealloc (im=0x558ed644) at Objects/classobject.c:2360
#1 0x555f6a61 in tupledealloc (op=0x5592010c) at Objects/tupleobject.c:220
#2 0x555aeed1 in instancemethod_call (func=0x558db8ec, arg=0x5592010c, kw=0x0) at Objects/classobject.c:2579
#3 0x5559aedb in PyObject_Call (func=0x558db8ec, arg=0x5592c0ec, kw=0x0) at Objects/abstract.c:2529
#4 0x5563d5af in PyEval_CallObjectWithKeywords (func=0x558db8ec, arg=0x5592c0ec, kw=0x0) at Python/ceval.c:3881
#5 0x5559ae6a in PyObject_CallObject (o=0x0, a=0x0) at Objects/abstract.c:2517
и значение, переданное в instancemethod_dealloc, равно:
(gdb) x 0x558ed644 0x558ed644: 0x00000000
Считаете ли вы, что это возможно?