在Cython中使用缓冲区API

Sin*_*ion 21 python memory-management cython pybuffer pep3118

我正在使用一个C库,它重复调用用户提供的函数指针以获取更多数据.我想以这样的方式,Python实现该回调可以返回任何合理的数据类型写一个用Cython包装一样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)
Run Code Online (Sandbox Code Playgroud)

我的代码编写会产生相同的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
Run Code Online (Sandbox Code Playgroud)

生成的C代码看起来像我认为它应该做的; 但这似乎不必要地在Python API中进行挖掘.Cython是否提供了更好的语法来实现这种效果?

aba*_*ert 2

如果您想支持实现新式或旧式缓冲区接口的每种变体的所有内容,那么您必须使用 C API。

\n\n

但如果你不关心旧式缓冲区,你几乎总是可以使用memoryview

\n\n
\n

Cython MemoryViews 支持几乎所有导出 Python 新型缓冲区接口的对象。这是 PEP 3118 中描述的缓冲区接口。NumPy 数组支持此接口,Cython 数组也是如此。\xe2\x80\x9c 几乎全部 \xe2\x80\x9d 是因为 Python 缓冲区接口允许数据数组中的元素本身是指针;Cython Memoryviews 尚不支持这一点。

\n
\n\n

这当然包括str(或者,在 3.x 中bytes)、bytearray等\xe2\x80\x94 如果您点击了该链接,您可能会注意到它链接到同一页面来解释您链接的内容以解释您想要的内容支持。

\n\n

对于一维字符数组(如str),它是:

\n\n
cdef char [:] gotdata\n
Run Code Online (Sandbox Code Playgroud)\n