I have a function (from an external Python library) that returns a memoryview
object that I want to process in Cython.
Is there a way to convert it to a typed memoryview of bytes (without copy) for efficiency? And how would I do that? This doesn't work:
mv = memoryview(b'1234')
cdef char[:] *tmv
tmv = mv
^
------------------------------------------------------------
/home/me/.cache/ipython/cython/_cython_magic_f9f608355444e2d6828580906623cea8.pyx:3:6: Cannot convert Python object to '__Pyx_memviewslice *'
This answer linked by @CodeSurgeon is a possibility to do it. However, since Cython 0.28 we have a much cleaner way - the typed read-only memoryviews:
%%cython
mv = memoryview(b'1234')
cdef const unsigned char[:] tmv=mv #"const" is possible since Cython 0.28
Obviously you can only read from this memoryview (this is a Good Thing) and there is no copying involved.
You could also say: but this is unsigned char
and not char
! True - this is also a Good Thing: bytes
are unsigned char
s and the whole point of typed memoryviews that you aren't mixing up the types!
Another reason I think the linked solution is kind of dangerous - you have the whole power of C to shoot yourself in the foot, because it casts types and constness away. See for example:
%%cython
def bad_things(a):
cdef const unsigned char[:] safe=a
cdef char *unsafe=<char *> &safe[0] #who needs const and types anyway?
unsafe[0]=52 #replace through `4`
And now:
>>> A=b'a'
>>> bad_things(A)
>>> print(A) #take it Python - I pwned your immutability!
b'4'
>>> print(b'a')
b'4'
>>> #Help! What are you doing Python?
Because Python has a pool of small strings, which are immutable (or so the Python thinks), and we have changed the object to which b'a'
is linked to b'4'
we should brace ourself for funny results and happy debugging...
In overall, this is a no-brainer: stick to typed memoryviews which guarantee type- and constness-safety.