Как написать функцию Cython, которая принимает объект строки байта (обычная строка, bytearray или другой объект, который следует за buffer protocol) как typed memoryview?Как использовать Cython типизированные представления памяти для принятия строк из Python?
Согласно странице учебника Unicode and Passing Strings Cython, следующее должно работать:
cpdef object printbuf(unsigned char[:] buf):
chars = [chr(x) for x in buf]
print repr(''.join(chars))
Это делает работу для ByteArray, и других доступных для записи буферов:
$ python -c 'import test; test.printbuf(bytearray("test\0ing"))'
'test\x00ing'
Но это не работает для нормальных строк и других буферных объектов только для чтения:
$ 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 при сгенерированном C-коде, Cython всегда передает флаг PyBUF_WRITABLE
в PyObject_GetBuffer()
, что объясняет исключение.
я могу вручную получить представление в буфер объект сам, но это не так удобно:
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'
Я делаю что-то неправильно, или же Cython не поддерживает принуждении только для чтения буфера объектов (такие как обычные строки) в типизированные объекты памяти?
Я нашел ваш патч [здесь] (https://mail.python.org/pipermail/cython-devel/2015-February/004316.html), даже добавление 'const' не помогает, поэтому это означает предлагаемую документацию не работает. – dashesy