在bytes对象上获取指向python memoryview的指针

时间:2017-01-20 12:55:42

标签: python pointers cython memoryview typed-memory-views

我有一个python memoryview指向一个bytes对象,我想在cython中执行一些处理。

我的问题是:

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

示例:

在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

如何解决这个问题?

4 个答案:

答案 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

一些警告:

  1. 请记住,bytes不可变,如果您尝试修改内存视图可能会导致问题
  2. 只要my_ptr有效,
  3. mview(以及array)才有效,因此请务必在需要时保留对array的引用访问数据,

答案 3 :(得分:0)

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

cdef const unsigned char[:] my_view = array
cdef char* my_ptr = <char*>&my_view[0]