我正在使用Cython编写Python 2.7扩展模块。如何创建实现新式缓冲区接口的Python对象,以包装由C库提供给我的一块内存?该内存块只是一串字节,而不是结构或多维数组。我被给予一个
我无法复制内存-这会损害我的应用程序性能。
对于旧式缓冲区对象,我可以简单地使用
我必须创建自己实现缓冲区接口的类吗?还是Cython提供了一种简单的方法来做到这一点?
我已经阅读了Cython文档中的Unicode and Passing Strings和Typed Memoryviews页面,但文档不够准确、不够完整,也没有看起来与我想要做的相似的示例。
以下是我尝试过的内容(
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 *
? - Kevinchar *
而不是const char *
,仍会发生相同的异常。感谢您指出这一点。 - Richard Hansentmp
声明为const,然后又修改了它。这是C标准中未定义的行为。既然您还说要避免复制内存,我对此有点困惑。 - Kevinconst
强制转换与我遇到的问题无关,但我已经更新了问题以消除const
强制转换。关于复制,那只是一些虚假代码,用来帮助设置问题代码。请查看修正后的问题;希望现在更清楚了。 - Richard Hansen