【发布时间】:2015-01-26 23:02:21
【问题描述】:
我正在 Cython 中编写 Python 2.7 扩展模块。 如何创建一个 Python 对象来实现新样式的缓冲区接口,该接口包装了 C 库提供给我的一块内存? 内存块只是一个字节字符串,而不是结构或多维数组。我得到了一个 const void * 指针和一个长度,以及一些关于指针保持有效时间的详细信息。
我无法复制内存——这会降低我的应用程序的性能。
对于旧式缓冲区对象,我可以简单地使用PyBuffer_FromMemory(),但我似乎找不到类似的简单方法来生成新式缓冲区对象。
我必须创建自己的实现缓冲区接口的类吗?或者 Cython 是否提供了一种简单的方法来做到这一点?
我已阅读 Cython 文档中的 Unicode and Passing Strings 和 Typed Memoryviews 页面,但文档不准确且不是很完整,并且没有与我想做的类似的示例。
这是我尝试过的 (test.pyx):
from libc.stdlib cimport malloc
from libc.string cimport memcpy
## pretend that this function is in some C library and that it does
## something interesting. (this function is unrelated to the problem
## I'm experiencing -- this is just an example function that returns a
## chunk of memory that I want to wrap in an object that follows the
## new buffer protocol.)
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
cpdef getbuf():
cdef const void *cstr
cdef size_t l
dummy_function(&cstr, &l)
## error: test.pyx:21:20: Invalid base type for memoryview slice: void
#cdef const void[:] ret = cstr[:l]
## error: test.pyx:24:9: Assignment to const 'ret'
#cdef const char[:] ret = cstr[:l]
## error: test.pyx:27:27: Cannot convert 'void const *' to memoryviewslice
#cdef char[:] ret = cstr[:l]
## this next attempt cythonizes, but raises an exception:
## $ python -c 'import test; test.getbuf()'
## Traceback (most recent call last):
## File "<string>", line 1, in <module>
## File "test.pyx", line 15, in test.getbuf (test.c:1411)
## File "test.pyx", line 38, in test.getbuf (test.c:1350)
## File "stringsource", line 614, in View.MemoryView.memoryview_cwrapper (test.c:6763)
## File "stringsource", line 321, in View.MemoryView.memoryview.__cinit__ (test.c:3309)
## BufferError: Object is not writable.
cdef char[:] ret = (<const char *>cstr)[:l]
## this raises the same exception as above
#cdef char[:] ret = (<char *>cstr)[:l]
return ret
【问题讨论】:
-
也许它失败了,因为您正在投射到
const char *而不是char *? -
@Kevin:我更新了我的问题,指出即使我转换为
char *而不是const char *,也会发生同样的异常。感谢您指出这一点。 -
在更详细地研究了这个问题之后,我想指出 memcpy 是非法的。您将
tmp声明为 const,然后对其进行了修改。这是 C 标准未定义的行为。既然你还说你试图避免复制内存,我在这一点上有点困惑。 -
@Kevin:感谢您的调查。抛弃
const与我遇到的问题无关,但我还是更新了问题以消除const演员。关于复制,这只是帮助设置问题代码的虚拟代码。请参阅修改后的问题;希望现在更清楚了。
标签: python python-2.7 cython python-c-extension memoryview