Tengo una C api que estoy interactuando con el paquete python ctypes. Todo funciona bien, excepto este pequeño bocado.¿Cómo puedo hacer que los métodos funcionen como devoluciones de llamada con los tipos de python?
para registrar funciones como las devoluciones de llamada a algunas notificaciones, i llamar a esta función:
void RegisterNotifyCallback(int loginId, int extraFlags, void *(*callbackFunc)(Notification *))
por lo que en pitón mi código es el siguiente:
CALLBACK = ctypes.CFUNCTYPE(None, ctypes.POINTER(Notification))
func = CALLBACK(myPythonCallback)
myLib.RegisterNofityCallback(45454, 0, func)
Si el valor de myPythonCallback es un FunctionType (es decir, no es un método), funciona bien y llama a la función de devolución de llamada con los parámetros correctos. Si es un MethodType, aún llama al método, pero luego explota con una segfault una vez que el método ha finalizado.
edición
para aclarar, cuando digo el tipo de función que quiero decir que myPythonCallback se define como una función,
def myPythonCallback(Notification):
...do something with the Notification object i get passed in
cuando digo que es un tipoMetodo, me refiero a un método de clase:
class MyClass(object):
def myPythonCallback(self, Notification):
...do something with Notification
Se explota en el segundo tipo.
¿Hay algo fácil alrededor de esto? ¿O alguien puede ofrecerme una explicación de por qué está sucediendo esto?
Muchas gracias, Al.
edición
Excavar un poco más con el BGF me da esto:
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
y el valor pasado a instancemethod_dealloc es:
(gdb) x 0x558ed644 0x558ed644: 0x00000000
Qué te parece este se puede arreglar?
¿Estás usando cdecl o stdcall en la API C? No sé a qué te refieres con la distinción entre tipo de función y tipo de método. Podría explicar más, posiblemente con muestras de código del formulario que funciona y el formulario que no. Por cierto, he creado devoluciones de llamadas con ctypes, así que estoy seguro de que es posible. –
Por favor, vea la edición. – AlMcLean