Mam api C, że jestem interfejs z pakietem python ctypes. Wszystko działa dobrze, z wyjątkiem tego małego smakołyku.Jak mogę uzyskać metody do pracy jako wywołania zwrotne w python ctypes?
Aby zarejestrować funkcje jak callbacków niektórych powiadomień, wzywam tę funkcję:
void RegisterNotifyCallback(int loginId, int extraFlags, void *(*callbackFunc)(Notification *))
tak w python mój kod wygląda następująco:
CALLBACK = ctypes.CFUNCTYPE(None, ctypes.POINTER(Notification))
func = CALLBACK(myPythonCallback)
myLib.RegisterNofityCallback(45454, 0, func)
Jeżeli wartość myPythonCallback jest FunctionType (tj nie jest to metoda), działa dobrze i wywołuje funkcję zwrotną z odpowiednimi parametrami. Jeśli jest to MethodType, nadal wywołuje metodę, ale następnie wysadza się z segfault po zakończeniu metody.
edit
celu wyjaśnienia, kiedy mówię typ funkcji i oznacza to, że myPythonCallback jest zdefiniowana jako funkcja,
def myPythonCallback(Notification):
...do something with the Notification object i get passed in
kiedy mówię, że to MethodType, to znaczy metoda klasy:
class MyClass(object):
def myPythonCallback(self, Notification):
...do something with Notification
Wysypuje się na drugi typ.
Czy jest to łatwe? A może ktoś zaoferuje mi wyjaśnienie, dlaczego tak się dzieje?
Wielkie dzięki, Al.
edit
Kopanie trochę dalej z GDB daje mi to:
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
i wartość przekazana do instancemethod_dealloc jest:
(gdb) x 0x558ed644 0x558ed644: 0x00000000
Czy myślisz to naprawić?
Czy używasz CDecl lub stdcall w C API? Nie wiem, co masz na myśli przez rozróżnienie między typem funkcji a typem metody. Czy mógłbyś wyjaśnić więcej, prawdopodobnie przy pomocy próbek kodu formularza, który działa, a formularza, który nie działa. Nawiasem mówiąc, udało mi się stworzyć wywołania zwrotne z ctypes, więc jestem pewien, że to jest możliwe. –
Proszę zobaczyć edycję. – AlMcLean