buffer.md
1> **Источник:** https://python-all.ru/3.6/c-api/buffer.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Протокол буфера89Некоторые объекты, доступные в Python, предоставляют доступ к лежащему в основе массиву памяти или *буферу*. К таким объектам относятся встроенные [`bytes`](https://python-all.ru/3.6/library/stdtypes.html#bytes) и [`bytearray`](https://python-all.ru/3.6/library/stdtypes.html#bytearray), а также некоторые расширяющие типы, например [`array.array`](https://python-all.ru/3.6/library/array.html#array.array). Сторонние библиотеки могут определять собственные типы для специальных целей, таких как обработка изображений или численный анализ.1011Хотя каждый из этих типов имеет свою семантику, их объединяет общая характеристика: все они основаны на возможно большом буфере памяти. В некоторых ситуациях желательно получить прямой доступ к этому буферу без промежуточного копирования.1213Python предоставляет такую возможность на уровне C в виде [буферного протокола](https://python-all.ru/3.6/c-api/buffer.html#bufferobjects). У этого протокола есть две стороны:1415- На стороне производителя тип может экспортировать «буферный интерфейс», который позволяет объектам этого типа предоставлять информацию о своём базовом буфере. Этот интерфейс описан в разделе [Buffer Object Structures](https://python-all.ru/3.6/c-api/typeobj.html#buffer-structs);16- На стороне потребителя доступно несколько способов получить указатель на необработанные базовые данные объекта (например, параметр метода).1718Простые объекты, такие как [`bytes`](https://python-all.ru/3.6/library/stdtypes.html#bytes) и [`bytearray`](https://python-all.ru/3.6/library/stdtypes.html#bytearray), предоставляют свой базовый буфер в байт-ориентированной форме. Возможны и другие формы; например, элементы, предоставляемые [`array.array`](https://python-all.ru/3.6/library/array.html#array.array), могут быть многобайтовыми значениями.1920Примером потребителя буферного интерфейса является метод [`write()`](https://python-all.ru/3.6/library/io.html#io.BufferedIOBase.write) файловых объектов: любой объект, который может экспортировать последовательность байтов через буферный интерфейс, может быть записан в файл. В то время как `write()` требуется только доступ на чтение к внутреннему содержимому переданного ему объекта, другие методы, такие как [`readinto()`](https://python-all.ru/3.6/library/io.html#io.BufferedIOBase.readinto), требуют доступа на запись к содержимому своего аргумента. Буферный интерфейс позволяет объектам выборочно разрешать или запрещать экспорт буферов с возможностью чтения-записи и только для чтения.2122Существует два способа для потребителя буферного интерфейса получить буфер над целевым объектом:2324- вызов [`PyObject_GetBuffer()`](https://python-all.ru/3.6/c-api/buffer.html#c.PyObject_GetBuffer) с правильными параметрами;25- вызов [`PyArg_ParseTuple()`](https://python-all.ru/3.6/c-api/arg.html#c.PyArg_ParseTuple) (или одного из его аналогов) с одним из `y*`, `w*` или `s*` [кодов формата](https://python-all.ru/3.6/c-api/arg.html#arg-parsing).2627В обоих случаях [`PyBuffer_Release()`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBuffer_Release) должен быть вызван, когда буфер больше не нужен. Невыполнение этого требования может привести к различным проблемам, таким как утечка ресурсов.2829## Структура буфера3031Структуры буферов (или просто «буферы») полезны как способ предоставления бинарных данных из другого объекта программисту на Python. Их также можно использовать как механизм среза с нулевым копированием. Благодаря возможности ссылаться на блок памяти, можно довольно легко предоставить любые данные программисту на Python. Память может быть большим константным массивом в C-расширении, необработанным блоком памяти для манипуляций перед передачей в библиотеку операционной системы или использоваться для передачи структурированных данных в их родном формате в памяти.3233В отличие от большинства типов данных, предоставляемых интерпретатором Python, буферы не являются указателями [`PyObject`](https://python-all.ru/3.6/c-api/structures.html#c.PyObject), а представляют собой простые структуры C. Это позволяет очень просто создавать и копировать их. Когда нужна универсальная обёртка вокруг буфера, можно создать объект [memoryview](https://python-all.ru/3.6/c-api/memoryview.html#memoryview-objects).3435Краткие инструкции по написанию экспортирующего объекта см. в разделе [Структуры буферных объектов](https://python-all.ru/3.6/c-api/typeobj.html#buffer-structs). Для получения буфера см. [`PyObject_GetBuffer()`](https://python-all.ru/3.6/c-api/buffer.html#c.PyObject_GetBuffer).3637**`Py_buffer`**3839**void \*`buf`**4041Указатель на начало логической структуры, описываемой полями буфера. Это может быть любое место в базовом физическом блоке памяти экспортёра. Например, при отрицательном [`strides`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.strides) значение может указывать на конец блока памяти.4243Для [непрерывных](https://python-all.ru/3.6/glossary.html#term-contiguous) массивов значение указывает на начало блока памяти.4445**void \*`obj`**4647Новая ссылка на экспортирующий объект. Ссылка принадлежит потребителю и автоматически уменьшается и устанавливается в *NULL* с помощью [`PyBuffer_Release()`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBuffer_Release). Это поле эквивалентно возвращаемому значению любой стандартной функции C-API.4849В особом случае для *временных* буферов, обёрнутых с помощью [`PyMemoryView_FromBuffer()`](https://python-all.ru/3.6/c-api/memoryview.html#c.PyMemoryView_FromBuffer) или [`PyBuffer_FillInfo()`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBuffer_FillInfo), это поле равно *NULL*. В общем случае экспортирующие объекты НЕ ДОЛЖНЫ использовать эту схему.5051**Py\_ssize\_t `len`**5253`product(shape) * itemsize`. Для непрерывных массивов это длина базового блока памяти. Для разрывных массивов это длина, которую имела бы логическая структура при копировании в непрерывное представление.5455Обращение к `((char *)buf)[0] up to ((char *)buf)[len-1]` допустимо только в том случае, если буфер получен через запрос, гарантирующий непрерывность. В большинстве случаев такой запрос будет [`PyBUF_SIMPLE`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBUF_SIMPLE) или [`PyBUF_WRITABLE`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBUF_WRITABLE).5657**int `readonly`**5859Индикатор, доступен ли буфер только для чтения. Это поле управляется флагом [`PyBUF_WRITABLE`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBUF_WRITABLE).6061**Py\_ssize\_t `itemsize`**6263Размер одного элемента в байтах. Совпадает со значением [`struct.calcsize()`](https://python-all.ru/3.6/library/struct.html#struct.calcsize), вызванной для не-NULL значений [`format`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.format).6465Важное исключение: если потребитель запрашивает буфер без флага [`PyBUF_FORMAT`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBUF_FORMAT), поле [`format`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.format) устанавливается в *NULL*, но [`itemsize`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.itemsize) сохраняет значение исходного формата.6667Если [`shape`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.shape) присутствует, равенство `product(shape) * itemsize == len` по-прежнему выполняется, и потребитель может использовать [`itemsize`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.itemsize) для навигации по буферу.6869Если [`shape`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.shape) равно *NULL* в результате запроса [`PyBUF_SIMPLE`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBUF_SIMPLE) или [`PyBUF_WRITABLE`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBUF_WRITABLE), потребитель должен игнорировать [`itemsize`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.itemsize) и считать `itemsize == 1`.7071**const char \*`format`**7273Строка, завершающаяся *нулевым символом*, в синтаксисе модуля [`struct`](https://python-all.ru/3.6/library/struct.html#module-struct), описывающая содержимое одного элемента. Если это *NULL*, подразумевается `"B"` (беззнаковые байты).7475Это поле управляется флагом [`PyBUF_FORMAT`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBUF_FORMAT).7677**int `ndim`**7879Количество измерений, которые память представляет как n-мерный массив. Если оно равно `0`, [`buf`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.buf) указывает на один элемент, представляющий скаляр. В этом случае [`shape`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.shape), [`strides`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.strides) и [`suboffsets`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.suboffsets) ДОЛЖНЫ быть *NULL*.8081Макрос `PyBUF_MAX_NDIM` ограничивает максимальное количество измерений до 64. Экспортёры ОБЯЗАНЫ соблюдать это ограничение; потребители многомерных буферов ДОЛЖНЫ уметь работать с размерностью до `PyBUF_MAX_NDIM`.8283**Py\_ssize\_t \*`shape`**8485Массив из `Py_ssize_t` длиной [`ndim`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.ndim), указывающий форму памяти в виде n-мерного массива. Обратите внимание, что `shape[0] * ... * shape[ndim-1] * itemsize` ДОЛЖНО быть равно [`len`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.len).8687Значения формы ограничены `shape[n] >= 0`. Случай `shape[n] == 0` требует особого внимания. Дополнительную информацию см. в разделе [сложные массивы](https://python-all.ru/3.6/c-api/buffer.html#complex-arrays).8889Массив формы доступен потребителю только для чтения.9091**Py\_ssize\_t \*`strides`**9293Массив из `Py_ssize_t` длиной [`ndim`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.ndim), задающий количество байтов, которое нужно пропустить, чтобы перейти к новому элементу в каждом измерении.9495Значения шага могут быть любыми целыми числами. Для обычных массивов шаги обычно положительны, но потребитель ДОЛЖЕН уметь обрабатывать случай `strides[n] <= 0`. Дополнительную информацию см. в разделе [сложные массивы](https://python-all.ru/3.6/c-api/buffer.html#complex-arrays).9697Массив шагов доступен потребителю только для чтения.9899**Py\_ssize\_t \*`suboffsets`**100101Массив из `Py_ssize_t` длиной [`ndim`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.ndim). Если `suboffsets[n] >= 0`, значения, хранящиеся по n-му измерению, являются указателями, и значение смещения подмассива указывает, сколько байтов добавить к каждому указателю после разыменования. Отрицательное значение смещения подмассива означает, что разыменование производиться не должно (шаг по непрерывному блоку памяти).102103Если все под-смещения отрицательны (т.е. разыменование не требуется), то это поле должно быть NULL (значение по умолчанию).104105Такой тип представления массива используется библиотекой Python Imaging Library (PIL). Дополнительную информацию о доступе к элементам такого массива см. в разделе [сложные массивы](https://python-all.ru/3.6/c-api/buffer.html#complex-arrays).106107Массив смещений подмассивов доступен потребителю только для чтения.108109**void \*`internal`**110111Предназначено для внутреннего использования экспортирующим объектом. Например, экспортёр может переинтерпретировать это значение как целое число и использовать для хранения флагов о том, нужно ли освобождать массивы shape, strides и suboffsets при освобождении буфера. Потребитель НЕ ДОЛЖЕН изменять это значение.112113## Типы запросов буфера114115Обычно буферы получают, отправляя запрос буфера экспортирующему объекту через [`PyObject_GetBuffer()`](https://python-all.ru/3.6/c-api/buffer.html#c.PyObject_GetBuffer). Поскольку сложность логической структуры памяти может сильно различаться, потребитель использует аргумент *flags* для указания точного типа буфера, с которым он может работать.116117Все поля [`Py_buffer`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer) однозначно определяются типом запроса.118119### поля, не зависящие от запроса120121Следующие поля не зависят от *flags* и всегда должны заполняться корректными значениями: [`obj`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.obj), [`buf`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.buf), [`len`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.len), [`itemsize`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.itemsize), [`ndim`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.ndim).122123### только для чтения, формат124125> **`PyBUF_WRITABLE`**126>127> Управляет полем [`readonly`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.readonly). Если флаг установлен, экспортёр ОБЯЗАН предоставить буфер для записи, иначе сообщить об ошибке. В противном случае экспортёр МОЖЕТ предоставить буфер только для чтения или для записи, но выбор ДОЛЖЕН быть единым для всех потребителей.128>129> **`PyBUF_FORMAT`**130>131> Управляет полем [`format`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.format). Если установлено, это поле ДОЛЖНО быть заполнено корректно. В противном случае это поле ДОЛЖНО быть *NULL*.132133[`PyBUF_WRITABLE`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBUF_WRITABLE) можно комбинировать (|) с любыми флагами из следующего раздела. Поскольку [`PyBUF_SIMPLE`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBUF_SIMPLE) определён как 0, [`PyBUF_WRITABLE`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBUF_WRITABLE) может использоваться как самостоятельный флаг для запроса простого буфера для записи.134135[`PyBUF_FORMAT`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBUF_FORMAT) можно комбинировать (по ИЛИ) с любыми флагами, кроме [`PyBUF_SIMPLE`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBUF_SIMPLE). Последний уже подразумевает формат `B` (беззнаковые байты).136137### форма, шаги, подсмещения138139Флаги, управляющие логической структурой памяти, перечислены в порядке убывания сложности. Обратите внимание, что каждый флаг содержит все биты флагов, расположенных ниже него.140141| Запрос | форма | шаги | подсмещения |142| --- | --- | --- | --- |143| `PyBUF_INDIRECT` | да | да | если необходимо |144| `PyBUF_STRIDES` | да | да | NULL |145| `PyBUF_ND` | да | NULL | NULL |146| `PyBUF_SIMPLE` | NULL | NULL | NULL |147148### запросы непрерывности149150[Непрерывность](https://python-all.ru/3.6/glossary.html#term-contiguous) по C или Fortran может быть явно запрошена, с информацией о шагах и без неё. Без информации о шагах буфер должен быть непрерывным по C.151152| Запрос | форма | шаги | подсмещения | непрерывность |153| --- | --- | --- | --- | --- |154| `PyBUF_C_CONTIGUOUS` | да | да | NULL | C |155| `PyBUF_F_CONTIGUOUS` | да | да | NULL | F |156| `PyBUF_ANY_CONTIGUOUS` | да | да | NULL | C или F |157| `PyBUF_ND` | да | NULL | NULL | C |158159### составные запросы160161Все возможные запросы полностью определяются некоторой комбинацией флагов из предыдущего раздела. Для удобства протокол буфера предоставляет часто используемые комбинации в виде отдельных флагов.162163В следующей таблице *U* обозначает неопределённую непрерывность. Потребителю придётся вызвать [`PyBuffer_IsContiguous()`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBuffer_IsContiguous), чтобы определить непрерывность.164165| Запрос | форма | шаги | подсмещения | непрерывность | только для чтения | формат |166| --- | --- | --- | --- | --- | --- | --- |167| `PyBUF_FULL` | да | да | если необходимо | U | 0 | да |168| `PyBUF_FULL_RO` | да | да | если необходимо | U | 1 или 0 | да |169| `PyBUF_RECORDS` | да | да | NULL | U | 0 | да |170| `PyBUF_RECORDS_RO` | да | да | NULL | U | 1 или 0 | да |171| `PyBUF_STRIDED` | да | да | NULL | U | 0 | NULL |172| `PyBUF_STRIDED_RO` | да | да | NULL | U | 1 или 0 | NULL |173| `PyBUF_CONTIG` | да | NULL | NULL | C | 0 | NULL |174| `PyBUF_CONTIG_RO` | да | NULL | NULL | C | 1 или 0 | NULL |175176## Комплексные массивы177178### В стиле NumPy: форма и шаги179180Логическая структура массивов в стиле NumPy определяется [`itemsize`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.itemsize), [`ndim`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.ndim), [`shape`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.shape) и [`strides`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.strides).181182Если `ndim == 0`, область памяти, на которую указывает [`buf`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.buf), интерпретируется как скаляр размера [`itemsize`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.itemsize). В этом случае, оба [`shape`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.shape) и [`strides`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.strides) равны *NULL*.183184Если [`strides`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.strides) равен *NULL*, массив интерпретируется как стандартный n-мерный C-массив. В противном случае потребитель должен обращаться к n-мерному массиву следующим образом:185186> `ptr = (char *)buf + indices[0] * strides[0] + ... + indices[n-1] * strides[n-1]` `item = *((typeof(item) *)ptr);`187188Как отмечалось выше, [`buf`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.buf) может указывать на любую позицию в реальном блоке памяти. Экспортер может проверить корректность буфера с помощью этой функции:189190```python191def verify_structure(memlen, itemsize, ndim, shape, strides, offset):192 """Проверить, что параметры представляют допустимый массив в пределах193 границ выделенной памяти:194 char *mem: начало физического блока памяти195 memlen: длина физического блока памяти196 смещение: (char *)buf - mem197 """198 if offset % itemsize:199 return False200 if offset < 0 or offset+itemsize > memlen:201 return False202 if any(v % itemsize for v in strides):203 return False204205 if ndim <= 0:206 return ndim == 0 and not shape and not strides207 if 0 in shape:208 return True209210 imin = sum(strides[j]*(shape[j]-1) for j in range(ndim)211 if strides[j] <= 0)212 imax = sum(strides[j]*(shape[j]-1) for j in range(ndim)213 if strides[j] > 0)214215 return 0 <= offset+imin and offset+imax+itemsize <= memlen216```217218### В стиле PIL: форма, шаги и suboffsets219220В дополнение к обычным элементам массивы в стиле PIL могут содержать указатели, по которым нужно перейти, чтобы получить следующий элемент в измерении. Например, обычный трехмерный C-массив `char v[2][2][3]` можно также рассматривать как массив из 2 указателей на 2 двумерных массива: `char (*v[2])[2][3]`. В представлении suboffsets эти два указателя могут быть встроены в начало [`buf`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.buf), указывая на два `char x[2][3]` массива, которые могут находиться в любом месте памяти.221222Ниже приведена функция, возвращающая указатель на элемент в N-мерном массиве, на который указывает N-мерный индекс, при наличии как ненулевых шагов (strides), так и субсмещений (suboffsets):223224```c225void *get_item_pointer(int ndim, void *buf, Py_ssize_t *strides,226 Py_ssize_t *suboffsets, Py_ssize_t *indices) {227 char *pointer = (char*)buf;228 int i;229 for (i = 0; i < ndim; i++) {230 pointer += strides[i] * indices[i];231 if (suboffsets[i] >=0 ) {232 pointer = *((char**)pointer) + suboffsets[i];233 }234 }235 return (void*)pointer;236}237```238239## Функции, связанные с буфером240241#### `int PyObject_CheckBuffer(PyObject *obj)`242243Возвращает `1`, если *obj* поддерживает интерфейс буфера, иначе `0`. Когда возвращается `1`, это не гарантирует, что [`PyObject_GetBuffer()`](https://python-all.ru/3.6/c-api/buffer.html#c.PyObject_GetBuffer) выполнится успешно. Эта функция всегда завершается успешно.244245#### `int PyObject_GetBuffer(PyObject *exporter, Py_buffer *view, int flags)`246247Отправить запрос *экспортёру* на заполнение *представления* в соответствии с *флагами*. Если экспортёр не может предоставить буфер нужного типа, он ОБЯЗАН возбудить исключение `PyExc_BufferError`, установить `view->obj` в *NULL* и вернуть `-1`.248249В случае успеха заполняет *view*, устанавливает `view->obj` в новую ссылку на *exporter* и возвращает 0. В случае цепочечных поставщиков буфера, которые перенаправляют запросы одному объекту, `view->obj` МОЖЕТ ссылаться на этот объект вместо *exporter* (см. [Структуры буферных объектов](https://python-all.ru/3.6/c-api/typeobj.html#buffer-structs)).250251Успешные вызовы [`PyObject_GetBuffer()`](https://python-all.ru/3.6/c-api/buffer.html#c.PyObject_GetBuffer) должны быть парными с вызовами [`PyBuffer_Release()`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBuffer_Release), как и в случае с `malloc()` и `free()`. Таким образом, после того как потребитель закончил работу с буфером, [`PyBuffer_Release()`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBuffer_Release) должен быть вызван ровно один раз.252253#### `void PyBuffer_Release(Py_buffer *view)`254255Освобождает буфер *view* и уменьшает счётчик ссылок для `view->obj`. Эту функцию ОБЯЗАТЕЛЬНО нужно вызывать, когда буфер больше не используется, иначе могут возникнуть утечки ссылок.256257Вызов этой функции для буфера, который не был получен через [`PyObject_GetBuffer()`](https://python-all.ru/3.6/c-api/buffer.html#c.PyObject_GetBuffer), является ошибкой.258259#### `Py_ssize_t PyBuffer_SizeFromFormat(const char *)`260261Возвращает подразумеваемое [`itemsize`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.itemsize) из [`format`](https://python-all.ru/3.6/c-api/buffer.html#c.Py_buffer.format). Эта функция ещё не реализована.262263#### `int PyBuffer_IsContiguous(Py_buffer *view, char order)`264265Возвращает `1`, если память, определяемая *view*, является C-style (*order* равен `'C'`) или Fortran-style (*order* равен `'F'`) [непрерывной (contiguous)](https://python-all.ru/3.6/glossary.html#term-contiguous), или любой из них (*order* равен `'A'`). Иначе возвращает `0`. Эта функция всегда завершается успешно.266267#### `int PyBuffer_ToContiguous(void *buf, Py_buffer *src, Py_ssize_t len, char order)`268269Копирует *len* байт из *src* в его непрерывное представление в *buf*. *order* может быть `'C'` или `'F'` (для порядка C-style или Fortran-style). В случае успеха возвращается `0`, при ошибке – `-1`.270271Эта функция завершается ошибкой, если *len* != *src-\>len*.272273#### `void PyBuffer_FillContiguousStrides(int ndims, Py_ssize_t *shape, Py_ssize_t *strides, int itemsize, char order)`274275Заполняет массив *strides* шагами в байтах (byte-strides) для [непрерывного](https://python-all.ru/3.6/glossary.html#term-contiguous) массива заданной формы с заданным количеством байтов на элемент (в стиле C, если *order* равен `'C'`, или в стиле Fortran, если *order* равен `'F'`).276277#### `int PyBuffer_FillInfo(Py_buffer *view, PyObject *exporter, void *buf, Py_ssize_t len, int readonly, int flags)`278279Обрабатывает запросы буфера для экспортёра, который хочет предоставить *buf* размером *len* с настройкой возможности записи в соответствии с *readonly*. *buf* интерпретируется как последовательность байтов без знака.280281Аргумент *flags* указывает тип запроса. Эта функция всегда заполняет *view* в соответствии с флагами, за исключением случаев, когда *buf* помечен как доступный только для чтения и в *flags* установлен [`PyBUF_WRITABLE`](https://python-all.ru/3.6/c-api/buffer.html#c.PyBUF_WRITABLE).282283В случае успеха установить `view->obj` в новую ссылку на *экспортёр* и вернуть 0. В противном случае возбудить исключение `PyExc_BufferError`, установить `view->obj` в *NULL* и вернуть `-1`.284285Если эта функция используется как часть [getbufferproc](https://python-all.ru/3.6/c-api/typeobj.html#buffer-structs), *exporter* ДОЛЖЕН быть установлен на экспортирующий объект, а *flags* должны передаваться без изменений. В противном случае *exporter* ДОЛЖЕН быть NULL.286