Domanda

La funzione myfunc C opera su un grande blocco di dati. I risultati vengono restituiti in blocchi ad una funzione di callback:

int myfunc(const char *data, int (*callback)(char *result, void *userdata), void *userdata);

Utilizzando ctypes , non è un grosso problema per chiamare myfunc dal codice Python, e per avere i risultati da restituire a una funzione di callback Python. Questo lavoro di richiamata bene.

myfunc = mylib.myfunc
myfunc.restype = c_int
myfuncFUNCTYPE = CFUNCTYPE(STRING, c_void_p)
myfunc.argtypes = [POINTER(c_char), callbackFUNCTYPE, c_void_p]

def mycb(result, userdata):
    print result
    return True

input="A large chunk of data."
myfunc(input, myfuncFUNCTYPE(mycb), 0)

Ma, esiste un modo per dare un oggetto Python (ad esempio una lista) come userdata alla funzione di callback? Al fine di riporre i pezzi di risultato, mi piacerebbe fare per esempio:.

def mycb(result, userdata):
    userdata.append(result)

userdata=[]

Ma non ho idea di come lanciare la lista Python per un c_void_p, in modo che possa essere utilizzato nella chiamata a myfunc.

La mia soluzione attuale è quella di implementare una lista concatenata come struttura ctypes, che è piuttosto ingombrante.

È stato utile?

Soluzione

Credo che si potrebbe utilizzare il Python API C di farlo ... forse si potrebbe usare un puntatore PyObject.

modifica : Come l'op sottolineato nei commenti, c'è già digitare facilmente disponibili in ctypes un py_object, quindi la soluzione è quello di creare prima un oggetto ctypes.py_object dalla lista Python e poi colata a c_void_p farla passare come argomento alla funzione C (penso che questo passaggio potrebbe non essere necessario come parametro digitato come void* dovrebbe accettare qualsiasi puntatore, e sarebbe più veloce per passare solo un byref). Nella richiamata, al contrario i passaggi sono fatto (casting dal puntatore nullo a un puntatore a py_object e quindi ottenere il valore dei contenuti).

Una soluzione potrebbe essere quella di utilizzare una chiusura per la vostra funzione di callback in modo che già conosce, in cui elencare deve aggiungere le voci ...

myfunc = mylib.myfunc
myfunc.restype = c_int
myfuncFUNCTYPE = CFUNCTYPE(STRING)
myfunc.argtypes = [POINTER(c_char), callbackFUNCTYPE]


def mycb(result, userdata):
    userdata.append(result)

input="A large chunk of data."
userdata = []
myfunc(input, myfuncFUNCTYPE(lambda x: mycb(x, userdata)))
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top