Sto lavorando con una libreria C che richiama ripetutamente un puntatore funzione fornito dall'utente per ottenere più dati. Mi piacerebbe scrivere un wrapper Cython in modo tale che l'implementazione Python di tale callback possa restituire qualsiasi tipo di dati ragionevole come str
, bytearray
, file mappati in memoria e così via (in particolare, supporta lo Buffer interface). quello che ho finora è:Utilizzo dell'API del buffer in Cython
from cpython.buffer cimport PyBUF_SIMPLE
from cpython.buffer cimport Py_buffer
from cpython.buffer cimport PyObject_GetBuffer
from cpython.buffer cimport PyBuffer_Release
from libc.string cimport memmove
cdef class _callback:
cdef public object callback
cdef public object data
cdef uint16_t GetDataCallback(void * userdata,
uint32_t wantlen, unsigned char * data,
uint32_t * gotlen):
cdef Py_buffer gotdata
box = <_callback> userdata
gotdata_object = box.callback(box.data, wantlen)
if not PyObject_CheckBuffer(gotdata_object):
# sulk
return 1
try:
PyObject_GetBuffer(gotdata_object, &gotdata, PyBUF_SIMPLE)
if not (0 < gotdata.len <= wantlen):
# sulk
return 1
memmove(data, gotdata.buf, gotdata.len)
return 0
finally:
PyBuffer_Release(&gotdata)
Il codice che voglio scrivere produrrebbe codice C equivalente, ma simile a questa:
from somewhere cimport something
from libc.string cimport memmove
cdef class _callback:
cdef public object callback
cdef public object data
cdef uint16_t GetDataCallback(void * userdata,
uint32_t wantlen, unsigned char * data,
uint32_t * gotlen):
cdef something gotdata
box = <_callback> userdata
gotdata = box.callback(box.data, wantlen)
if not (0 < gotdata.len <= wantlen):
# sulk
return 1
memmove(data, gotdata.buf, gotdata.len)
return 0
Il codice C generato assomiglia a quello che penso dovrebbe fare; ma questo sembra come scavare inutilmente nell'API Python. Cython fornisce una sintassi migliore per ottenere questo effetto?