Я работаю с библиотекой C, которая неоднократно вызывает указатель на функцию, предоставленную пользователем, чтобы получить больше данных. Я хотел бы написать оболочку Cython таким образом, что реализация этого обратного вызова на Python может вернуть любой разумный тип данных, такой как str
, bytearray
, файлы с отображением памяти и т.д. (В частности, поддерживает Интерфейс буфера). что я до сих пор:
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)
Код, который я хочу написать, приведет к эквивалентному коду C, но выглядит так:
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
Сгенерированный код C выглядит так, как я думаю, он должен делать; но это похоже на то, что в API Python необязательно. Обеспечивает ли Cython лучший синтаксис для достижения этого эффекта?