我有一个python memoryview
指向一个bytes
对象,我想在cython中执行一些处理。
我的问题是:
bytes
对象不可写,cython不允许从中构造类型化的(cython)内存视图示例:
在python中:
array = memoryview(b'abcdef')[3:]
在cython中:
cdef char * my_ptr = &array[0]
无法使用以下邮件进行编译:{{1}} Cannot take address of Python variable
在运行时失败并显示以下消息:cdef char[:] my_view = array
如何解决这个问题?
答案 0 :(得分:2)
好的,在深入了解python api之后,我找到了一个解决方案来获取指向内存视图中bytes
对象缓冲区的指针(此处称为bytes_view = memoryview(bytes())
)。也许这有助于其他人:
from cpython.buffer cimport PyObject_GetBuffer, PyBuffer_Release, PyBUF_ANY_CONTIGUOUS, PyBUF_SIMPLE
cdef Py_buffer buffer
cdef char * my_ptr
PyObject_GetBuffer(bytes, &buffer, PyBUF_SIMPLE | PyBUF_ANY_CONTIGUOUS)
try:
my_ptr = <char *>buffer.buf
# use my_ptr
finally:
PyBuffer_Release(&buffer)
答案 1 :(得分:1)
您可以使用bytearray
创建可变的内存视图。请注意,这不会更改字符串,只会更改bytearray
data = bytearray('python')
view = memoryview(data)
view[0] = 'c'
print data
# cython
答案 2 :(得分:1)
使用bytearray
(根据@ CheeseLover的回答)可能是正确的做事方式。我的建议是完全在bytearrays
工作,从而避免临时转换。但是:
char*
can be directly created from a Python string(或bytes
) - 请参阅链接部分的结尾:
cdef char * my_ptr = array
# you can then convert to a memoryview as normal in Cython
cdef char[:] mview = <char[:len(array)]>my_ptr
一些警告:
bytes
不可变,如果您尝试修改内存视图可能会导致问题my_ptr
有效,mview
(以及array
)才有效,因此请务必在需要时保留对array
的引用访问数据,答案 3 :(得分:0)
如果您不希望cython memoryview因“底层缓冲区不可写”而失败,则根本不应该要求可写缓冲区。一旦进入C域,就可以立即处理该可写性。如此有效:
cdef const unsigned char[:] my_view = array
cdef char* my_ptr = <char*>&my_view[0]