I have a python memoryview
pointing to a bytes
object on which I would like to perform some processing in cython.
My problem is:
- because the
bytes
object is not writable, cython does not allow constructing a typed (cython) memoryview from it - I cannot use pointers either because I cannot get a pointer to the memoryview start
Example:
In python:
array = memoryview(b'abcdef')[3:]
In cython:
cdef char * my_ptr = &array[0]
fails to compile with the message:Cannot take address of Python variable
cdef char[:] my_view = array
fails at runtime with the message:BufferError: memoryview: underlying buffer is not writable
How does one solve this?
Using a
bytearray
(as per @CheeseLover's answer) is probably the right way of doing things. My advice would be to work entirely inbytearrays
thereby avoiding temporary conversions. However:char*
can be directly created from a Python string (orbytes
) - see the end of the linked section:A couple of warnings:
bytes
is not mutable and if you attempt to modify that memoryview is likely to cause issuesmy_ptr
(and thusmview
) are only valid so long asarray
is valid, so be sure to keep a reference toarray
for as long as you need access ti the data,If you don't want cython memoryview to fail with 'underlying buffer is not writable' you simply should not ask for a writable buffer. Once you're in C domain you can summarily deal with that writability. So this works:
You can use
bytearray
to create a mutable memoryview. Please note that this won't change the string, only thebytearray
Ok, after digging through the python api I found a solution to get a pointer to the
bytes
object's buffer in a memoryview (here calledbytes_view = memoryview(bytes())
). Maybe this helps somebody else: