Come posso scrivere una funzione Cython che accetta un oggetto stringa di byte (una stringa normale, un bytearray o un altro oggetto che segue lo buffer protocol) come typed memoryview?Come utilizzare le visioni di memoria tipizzate da Cython per accettare stringhe da Python?
Secondo la pagina di esercitazione Unicode and Passing Strings Cython, il seguente dovrebbe funzionare:
cpdef object printbuf(unsigned char[:] buf):
chars = [chr(x) for x in buf]
print repr(''.join(chars))
funziona per bytearrays e altri buffer scrivibili:
$ python -c 'import test; test.printbuf(bytearray("test\0ing"))'
'test\x00ing'
Ma non funziona per le stringhe normali e altri oggetti buffer di sola lettura:
$ python -c 'import test; test.printbuf("test\0ing")'
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "test.pyx", line 1, in test.printbuf (test.c:1417)
File "stringsource", line 614, in View.MemoryView.memoryview_cwrapper (test.c:6795)
File "stringsource", line 321, in View.MemoryView.memoryview.__cinit__ (test.c:3341)
BufferError: Object is not writable.
Looki ng al codice C generato, Cython passa sempre il flag PyBUF_WRITABLE
a PyObject_GetBuffer()
, che spiega l'eccezione.
posso ottenere manualmente una vista nel buffer obiettare me stesso, ma non è così conveniente:
from cpython.buffer cimport \
PyBUF_SIMPLE, PyBUF_WRITABLE, \
PyObject_CheckBuffer, PyObject_GetBuffer, PyBuffer_Release
cpdef object printbuf(object buf):
if not PyObject_CheckBuffer(buf):
raise TypeError("argument must follow the buffer protocol")
cdef Py_buffer view
PyObject_GetBuffer(buf, &view, PyBUF_SIMPLE)
try:
chars = [chr((<unsigned char *>view.buf)[i])
for i in range(view.len)]
print repr(''.join(chars))
finally:
PyBuffer_Release(&view)
$ python -c 'import test; test.printbuf(bytearray("test\0ing"))'
'test\x00ing'
$ python -c 'import test; test.printbuf("test\0ing")'
'test\x00ing'
sto facendo qualcosa di sbagliato, o non Cython non supportare costringere sola lettura tampone oggetti (come le normali stringhe) in oggetti memoryview digitati?
Ho trovato la tua patch [qui] (https://mail.python.org/pipermail/cython-devel/2015-February/004316.html) aggiungendo anche 'const' non aiuta, quindi questo significa la documentazione suggerita non funziona. – dashesy