2013-04-20 76 views
20

我正在使用一个C库,它重复调用用户提供的函数指针来获取更多数据。我想编写一个Cython包装器,使得该回调的Python实现可以返回任何合理的数据类型,如str,bytearray,内存映射文件等(具体而言,支持Buffer interface)。我至今是:在Cython中使用buffer buffer

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是否提供更好的语法来实现这种效果?

回答

2

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

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

用Cython memoryviews支持几乎所有对象导出Python这样的新风格缓冲区的接口。这是PEP 3118中描述的缓冲区接口.NumPy数组支持这个接口,就像Cython数组一样。 “几乎所有”是因为Python缓冲接口允许数据数组中的元素本身是指针; Cython内存视图还不支持这一点。

这当然包括str(或者,在3.x中,bytes),bytearray等,如果您使用的链接,你可能会注意到它链接到同一个页面来解释什么支持你链接解释你想要支持什么。

对于字符(比如str)的一维数组,这是:

cdef char [:] gotdata