7

我有一个 pythonmemoryview指向一个bytes我想在 cython 中执行一些处理的对象。

我的问题是:

  • 因为bytes对象不可写,cython 不允许从中构造类型化(cython)内存视图
  • 我也不能使用指针,因为我无法获得指向 memoryview 开始的指针

例子:

在蟒蛇中:

array = memoryview(b'abcdef')[3:]

在赛通中:

  • cdef char * my_ptr = &array[0]无法编译并显示以下消息:Cannot take address of Python variable
  • cdef char[:] my_view = array在运行时失败并显示以下消息:BufferError: memoryview: underlying buffer is not writable

如何解决这个问题?

4

4 回答 4

5

bytes好的,在挖掘了 python api 之后,我找到了一个解决方案,可以在 memoryview中获取指向对象缓冲区的指针(这里称为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)
于 2017-01-20T17:42:49.763 回答
3

使用bytearray(根据@CheeseLover 的回答)可能是正确的做事方式。我的建议是完全投入工作,bytearrays从而避免临时转换。然而:

char*可以直接从 Python 字符串(或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

几个警告:

  1. 请记住,它bytes是不可变的,如果您尝试修改该 memoryview 可能会导致问题
  2. my_ptr(因此mview)只有在有效时才有效,所以只要您需要访问数据,请array务必保留对的引用,array
于 2017-01-20T17:18:04.047 回答
2

您可以使用bytearray创建可变内存视图。请注意,这不会更改字符串,只会更改bytearray

data = bytearray('python')
view = memoryview(data)
view[0] = 'c'
print data
# cython
于 2017-01-20T14:46:40.013 回答
1

如果您不希望 cython memoryview 因“底层缓冲区不可写”而失败,您根本不应该要求可写缓冲区。一旦进入 C 域,您就可以简单地处理这种可写性。所以这有效:

cdef const unsigned char[:] my_view = array
cdef char* my_ptr = <char*>&my_view[0]
于 2019-02-15T15:38:17.057 回答