Почему невозможно получить Py_buffer из объекта массива? - PullRequest
6 голосов
/ 02 февраля 2011

В документации python для массива четко указано, что массив соответствует интерфейсу буфера.Он даже предлагает не использовать метод buffer_info ().Но когда я пытаюсь получить Py_Buffer из кода C / C ++ с помощью PyObject_GetBuffer () или использовать представление памяти python, я получаю ошибку.

Например, в python (я использую версию 2.7):

>>> a = array.array('c')
>>> memoryview(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot make memory view because object does not have the buffer interface

Фактически, когда я выполняю поиск в кодовой базе Python, только для bytearrayobject (bytearray), memoryobject (memoryview) и stringobject (str) на них устанавливается обязательный флаг Py_TPFLAGS_HAVE_NEWBUFFER.Насколько я понимаю, документация неверна; массив не поддерживает интерфейс буфера.

Я мог бы использовать bytearray, который поддерживает интерфейс буфера, проблема в том, что мне нужен практичный метод массива fromfile () для чтения в буфере, который яможно использовать в моем коде C / C ++.

Есть ли альтернатива, которая позволила бы мне прочитать файл в буфер и использовать этот буфер из кода C, а не задействовать копии памяти?(Я хочу обрабатывать большие двоичные файлы, а копирование - менее желательный вариант).

Ответы [ 2 ]

4 голосов
/ 02 февраля 2011

memoryview работает только с объектами, которые поддерживают буферный интерфейс Python 3. array.array в Python 3 делает, но не в Python 2.7. Вы можете подать отчет об ошибке для этого. Просто используйте bytearray (или str, если вы используете его только для чтения). Оба поддерживают memoryview просто отлично.

2 голосов
/ 04 мая 2014

Python 2.6+ имеет два разных буферных интерфейса, как и два разных типа классов: классическая версия и версия Python 3.

Из Справочного руководства по API Python / C :

Два примера объектов, которые поддерживают интерфейс буфера, это строки и массивы. Строковый объект предоставляет содержимое символа в байтово-ориентированной форме интерфейса буфера. Массив может предоставлять свое содержимое только через интерфейс буфера старого стиля. Это ограничение не распространяется на Python 3, где объекты памяти могут также создаваться из массивов.

В коде Python 2.7 вы можете работать с буферами старого стиля, используя функцию buffer, и буферами нового стиля, используя memoryview. Python 3 поддерживает только последнее.

Аналогичное различие существует в Python 2 C API; PyObject_GetBuffer для нового интерфейса буфера, PyBuffer_FromObject / PyBuffer_FromReadWriteObject для старого интерфейса буфера (и должен работать для массивов). См. Ссылку выше для получения дополнительной информации.

...