Ich arbeite mit einer C-Bibliothek, die wiederholt einen benutzerdefinierten Funktionszeiger ruft, um mehr Daten zu erhalten. Ich möchte einen Cython-Wrapper so schreiben, dass die Python-Implementierung dieses Callbacks jeden vernünftigen Datentyp wie str
, bytearray
, Speicherabbilddateien usw. zurückgeben kann (unterstützt speziell die Buffer interface). was ich bisher habe, ist:Verwenden der Puffer-API 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)
Der Code, den ich wollen Äquivalent C-Code zu schreiben, produzieren würde, aber wie folgt aussehen:
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
Der C-Code erzeugt aussieht, was ich denke, es sollte tun; aber das scheint sich in der Python API unnötig herumzuwühlen. Bietet Cython eine schönere Syntax, um diesen Effekt zu erzielen?