【问题标题】:Using the buffer API in Cython在 Cython 中使用缓冲区 API
【发布时间】:2013-04-20 17:00:09
【问题描述】:

我正在使用一个 C 库,该库反复调用用户提供的函数指针以获取更多数据。我想编写一个 Cython 包装器,使得该回调的 Python 实现可以返回任何合理的数据类型,如 strbytearray、内存映射文件等(具体来说,支持 Buffer interface )。到目前为止我所拥有的是:

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 代码看起来像我认为它应该做的;但这似乎是不必要地在 Python API 中挖掘。 Cython 是否提供了更好的语法来实现这种效果?

【问题讨论】:

    标签: python memory-management cython pybuffer pep3118


    【解决方案1】:

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

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

    Cython 内存视图支持几乎所有对象导出 Python 新样式缓冲区的接口。这是 PEP 3118 中描述的缓冲区接口。NumPy 数组支持此接口,Cython 数组也是如此。 “几乎所有”是因为 Python 缓冲区接口允许数据数组中的元素本身是指针; Cython 内存视图尚不支持此功能。

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

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

    cdef char [:] gotdata
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-07
      • 1970-01-01
      • 2017-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多