Подтвердить что ты не робот

Как использовать Cython типизированные представления памяти для принятия строк из Python?

Как написать функцию Cython, которая принимает объект строковой строки (нормальная строка, bytearray или другой объект, следующий за протоколом ) в качестве типизированное представление памяти?

В соответствии с Unicode и Passing Strings на странице руководства Cython должно работать следующее:

cpdef object printbuf(unsigned char[:] buf):
    chars = [chr(x) for x in buf]
    print repr(''.join(chars))

Он работает для bytearrays и других записываемых буферов:

$ 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.

Посмотрев на сгенерированный код 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 не поддерживает принудительное использование объектов буфера только для чтения (например, обычных строк) в типизированные объекты памяти?

4b9b3361

Ответ 1

Несмотря на документацию, указывающую на то, что Cython (по крайней мере, до версии 0.22) поддерживает не поддержку принудительного ввода объектов буфера только для чтения в типизированные объекты памяти. Cython всегда передает флаг PyBUF_WRITABLE PyObject_GetBuffer(), даже если ему не нужен доступ на запись. Это приводит к тому, что объекты буфера только для чтения создают исключение.

I поднял эту проблему в списке рассылки разработчиков Cython и даже включил (очень грубый) патч. Я никогда не получал ответа, поэтому я предполагаю, что разработчики Cython не заинтересованы в исправлении этой ошибки.