Tôi đang làm việc với thư viện C liên tục gọi một con trỏ hàm do người dùng cung cấp để nhận thêm dữ liệu. Tôi muốn viết một trình bao bọc Cython theo cách mà việc thực thi Python của cuộc gọi đó có thể trả về bất kỳ kiểu dữ liệu hợp lý nào như str
, bytearray
, các tệp ánh xạ bộ nhớ, v.v ... (cụ thể, hỗ trợ Buffer interface). những gì tôi có cho đến nay là:Sử dụng API bộ đệm trong 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)
Code tôi muốn viết sẽ tạo ra mã C tương đương, nhưng trông như thế này:
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
Mã C tạo ra trông giống như những gì tôi nghĩ rằng nó nên làm; nhưng điều này có vẻ giống như việc đào bới xung quanh trong API Python một cách không cần thiết. Cython có cung cấp cú pháp đẹp hơn để đạt được hiệu ứng này không?