Domanda

Sto cercando di scrivere un wrapper per un programma C in modo che possa chiamare da Python. Sto usando Cython per fare questo. La funzione C richiede una funzione di callback come argomento, ma questa funzione indietro chiamata sarà noto solo in fase di esecuzione del programma pitone. Sono stato alla ricerca come fare questo e sembra non ci sia una soluzione semplice, ma il seguente sembra funzionare:

#python.py

libc = cdll.LoadLibrary("myfunc.so") #Callback function is defined in myfunc.so 
....
c_wrapper(libc.fun, ...)

.

#c_wrapper.pyx

cdef extern void mainfunction(void *F, ...) #The intial C function we are wrapping
ctypedef void (*myfuncptr) () 

def c_wrapper(f, ...) # our function pointer is passed to the wrapper as a Python object
    cdef myfuncptr thisfunc
    thisfunc = (<myfuncptr*><size_t>addressof(f))[0]
    mainfunction(thisfunc, ...)

Questo metodo funziona per funzioni C e Fortran (Io parto dal presupposto che funzionerà per la maggior parte languges compilati) e le funzioni Python (utilizzando i tipi C), ma sembra un po 'imbarazzante. C'è un modo più semplice di fare questo in Cython?

Grazie

EDIT: Non sono in grado di cambiare la libreria C che sto cercando di avvolgere

È stato utile?

Soluzione

vi immagino siete a conoscenza di questo ?

E 'possibile chiamare il mio codice Python dal C?

Risposta: Sì, facilmente. Seguire l'esempio di Demos / richiamata / nel distribuzione del codice sorgente Cython

Quindi, sapendo che si può DLOAD tua funzione principale, prendiamo un altro approccio. Ho scritto un paio di funzioni stupide per testare questo:

/* lib.c -> lib.so */
#include <stdio.h>

void fn1(void) {
        puts("Called function 1");
}

void fn2(void) {
        puts("Called function 2");
}

dunque, la funzione che prende il callback

/* main.c -> main.so */

typedef void (*callback)();

void mainfunction(void *F) {
        ((callback)F)();
}

che può essere trasmesso direttamente da Python:

>>> from ctypes import cdll
>>> lib = cdll.LoadLibrary('./lib.so')
>>> main = cdll.LoadLibrary('./main.so')
>>> main.mainfunction(lib.fn1)
Called function 1
>>> main.mainfunction(lib.fn2)
Called function 2

E ora, cerchiamo di avvolgere una funzione Python:

>>> from ctypes import CFUNCTYPE
>>> def pyfn():
...     print "Called the Python function"
... 
>>> CWRAPPER = CFUNCTYPE(None)

>>> wrapped_py_func = CWRAPPER(pyfn)
>>> main.mainfunction(wrapped_py_func)
Called the Python function
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top