您可以定义一个扩展类型通过定义来实现缓冲区协议__getbuffer__
and __releasebuffer__
特殊方法。例如:
from cpython.buffer cimport PyBuffer_FillInfo
from libc.stdlib cimport free, malloc
from libc.string cimport memcpy
cdef void dummy_function(const void **p, size_t *l):
cdef void *tmp = malloc(17)
memcpy(tmp, "some test\0 bytes", 17)
p[0] = tmp
l[0] = 17
cdef void free_dummy_data(const void *p, size_t l, void *arg):
free(<void *>p)
cpdef getbuf():
cdef const void *p
cdef size_t l
dummy_function(&p, &l)
return MemBuf_init(p, l, &free_dummy_data, NULL)
ctypedef void dealloc_callback(const void *p, size_t l, void *arg)
cdef class MemBuf:
cdef const void *p
cdef size_t l
cdef dealloc_callback *dealloc_cb_p
cdef void *dealloc_cb_arg
def __getbuffer__(self, Py_buffer *view, int flags):
PyBuffer_FillInfo(view, self, <void *>self.p, self.l, 1, flags)
def __releasebuffer__(self, Py_buffer *view):
pass
def __dealloc__(self):
if self.dealloc_cb_p != NULL:
self.dealloc_cb_p(self.p, self.l, self.dealloc_cb_arg)
# Call this instead of constructing a MemBuf directly. The __cinit__
# and __init__ methods can only take Python objects, so the real
# constructor is here. See:
# https://mail.python.org/pipermail/cython-devel/2012-June/002734.html
cdef MemBuf MemBuf_init(const void *p, size_t l,
dealloc_callback *dealloc_cb_p,
void *dealloc_cb_arg):
cdef MemBuf ret = MemBuf()
ret.p = p
ret.l = l
ret.dealloc_cb_p = dealloc_cb_p
ret.dealloc_cb_arg = dealloc_cb_arg
return ret
与上述(命名为test.pyx
)你会得到以下行为:
$ python -c 'import test; print repr(memoryview(test.getbuf()).tobytes())'
'some test\x00 bytes\x00'
我不知道是否有更简单的方法。