buffer.md
1> **Источник:** https://python-all.ru/3.5/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.5/library/functions.html#bytes) и [`bytearray`](https://python-all.ru/3.5/library/functions.html#bytearray), а также некоторые расширяющие типы, например [`array.array`](https://python-all.ru/3.5/library/array.html#array.array). Сторонние библиотеки могут определять собственные типы для специальных целей, таких как обработка изображений или численный анализ.1011Хотя каждый из этих типов имеет свою семантику, их объединяет общая характеристика: все они основаны на возможно большом буфере памяти. В некоторых ситуациях желательно получить прямой доступ к этому буферу без промежуточного копирования.1213Python предоставляет такую возможность на уровне C в виде [буферного протокола](https://python-all.ru/3.5/c-api/buffer.html#bufferobjects). У этого протокола есть две стороны:1415- На стороне производителя тип может экспортировать «буферный интерфейс», который позволяет объектам этого типа предоставлять информацию о своём базовом буфере. Этот интерфейс описан в разделе [Buffer Object Structures](https://python-all.ru/3.5/c-api/typeobj.html#buffer-structs);16- На стороне потребителя доступно несколько способов получить указатель на необработанные базовые данные объекта (например, параметр метода).1718Простые объекты, такие как [`bytes`](https://python-all.ru/3.5/library/functions.html#bytes) и [`bytearray`](https://python-all.ru/3.5/library/functions.html#bytearray), предоставляют свой базовый буфер в байт-ориентированной форме. Возможны и другие формы; например, элементы, предоставляемые [`array.array`](https://python-all.ru/3.5/library/array.html#array.array), могут быть многобайтовыми значениями.1920Примером потребителя буферного интерфейса является метод [`write()`](https://python-all.ru/3.5/library/io.html#io.BufferedIOBase.write) файловых объектов: любой объект, который может экспортировать последовательность байтов через буферный интерфейс, может быть записан в файл. В то время как `write()` требуется только доступ на чтение к внутреннему содержимому переданного ему объекта, другие методы, такие как [`readinto()`](https://python-all.ru/3.5/library/io.html#io.BufferedIOBase.readinto), требуют доступа на запись к содержимому своего аргумента. Буферный интерфейс позволяет объектам выборочно разрешать или запрещать экспорт буферов с возможностью чтения-записи и только для чтения.2122Существует два способа для потребителя буферного интерфейса получить буфер над целевым объектом:2324- вызов [`PyObject_GetBuffer()`](https://python-all.ru/3.5/c-api/buffer.html#c.PyObject_GetBuffer) с правильными параметрами;25- вызов [`PyArg_ParseTuple()`](https://python-all.ru/3.5/c-api/arg.html#c.PyArg_ParseTuple) (или одного из его аналогов) с одним из `y*`, `w*` или `s*` [кодов формата](https://python-all.ru/3.5/c-api/arg.html#arg-parsing).2627В обоих случаях [`PyBuffer_Release()`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBuffer_Release) должен быть вызван, когда буфер больше не нужен. Невыполнение этого требования может привести к различным проблемам, таким как утечка ресурсов.2829## Структура буфера3031Структуры буферов (или просто «буферы») полезны как способ предоставления бинарных данных из другого объекта программисту на Python. Их также можно использовать как механизм среза с нулевым копированием. Благодаря возможности ссылаться на блок памяти, можно довольно легко предоставить любые данные программисту на Python. Память может быть большим константным массивом в C-расширении, необработанным блоком памяти для манипуляций перед передачей в библиотеку операционной системы или использоваться для передачи структурированных данных в их родном формате в памяти.3233В отличие от большинства типов данных, предоставляемых интерпретатором Python, буферы не являются указателями [`PyObject`](https://python-all.ru/3.5/c-api/structures.html#c.PyObject), а представляют собой простые структуры C. Это позволяет очень просто создавать и копировать их. Когда нужна универсальная обёртка вокруг буфера, можно создать объект [memoryview](https://python-all.ru/3.5/c-api/memoryview.html#memoryview-objects).3435Краткие инструкции по написанию экспортирующего объекта см. в разделе [Структуры буферных объектов](https://python-all.ru/3.5/c-api/typeobj.html#buffer-structs). Для получения буфера см. [`PyObject_GetBuffer()`](https://python-all.ru/3.5/c-api/buffer.html#c.PyObject_GetBuffer).3637**`Py_buffer`**3839**void \*`buf`**4041Указатель на начало логической структуры, описываемой полями буфера. Это может быть любое место в базовом физическом блоке памяти экспортёра. Например, при отрицательном [`strides`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.strides) значение может указывать на конец блока памяти.4243Для [непрерывных](https://python-all.ru/3.5/glossary.html#term-contiguous) массивов значение указывает на начало блока памяти.4445**void \*`obj`**4647Новая ссылка на экспортирующий объект. Ссылка принадлежит потребителю и автоматически уменьшается и устанавливается в *NULL* с помощью [`PyBuffer_Release()`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBuffer_Release). Это поле эквивалентно возвращаемому значению любой стандартной функции C-API.4849В особом случае для *временных* буферов, обёрнутых с помощью [`PyMemoryView_FromBuffer()`](https://python-all.ru/3.5/c-api/memoryview.html#c.PyMemoryView_FromBuffer) или [`PyBuffer_FillInfo()`](https://python-all.ru/3.5/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.5/c-api/buffer.html#c.PyBUF_SIMPLE) или [`PyBUF_WRITABLE`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBUF_WRITABLE).5657**int `readonly`**5859Индикатор, доступен ли буфер только для чтения. Это поле управляется флагом [`PyBUF_WRITABLE`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBUF_WRITABLE).6061**Py\_ssize\_t `itemsize`**6263Размер одного элемента в байтах. Совпадает со значением [`struct.calcsize()`](https://python-all.ru/3.5/library/struct.html#struct.calcsize), вызванной для не-NULL значений [`format`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.format).6465Важное исключение: если потребитель запрашивает буфер без флага [`PyBUF_FORMAT`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBUF_FORMAT), поле [`format`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.format) устанавливается в *NULL*, но [`itemsize`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.itemsize) сохраняет значение исходного формата.6667Если [`shape`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.shape) присутствует, равенство `product(shape) * itemsize == len` по-прежнему выполняется, и потребитель может использовать [`itemsize`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.itemsize) для навигации по буферу.6869Если [`shape`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.shape) равно *NULL* в результате запроса [`PyBUF_SIMPLE`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBUF_SIMPLE) или [`PyBUF_WRITABLE`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBUF_WRITABLE), потребитель должен игнорировать [`itemsize`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.itemsize) и считать `itemsize == 1`.7071**const char \*`format`**7273Строка, завершающаяся *нулевым символом*, в синтаксисе модуля [`struct`](https://python-all.ru/3.5/library/struct.html#module-struct), описывающая содержимое одного элемента. Если это *NULL*, подразумевается `"B"` (беззнаковые байты).7475Это поле управляется флагом [`PyBUF_FORMAT`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBUF_FORMAT).7677**int `ndim`**7879Количество измерений, которые память представляет как n-мерный массив. Если оно равно `0`, [`buf`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.buf) указывает на один элемент, представляющий скаляр. В этом случае [`shape`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.shape), [`strides`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.strides) и [`suboffsets`](https://python-all.ru/3.5/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.5/c-api/buffer.html#c.Py_buffer.ndim), указывающий форму памяти в виде n-мерного массива. Обратите внимание, что `shape[0] * ... * shape[ndim-1] * itemsize` ДОЛЖНО быть равно [`len`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.len).8687Значения формы ограничены `shape[n] >= 0`. Случай `shape[n] == 0` требует особого внимания. Дополнительную информацию см. в разделе [сложные массивы](https://python-all.ru/3.5/c-api/buffer.html#complex-arrays).8889Массив формы доступен потребителю только для чтения.9091**Py\_ssize\_t \*`strides`**9293Массив из `Py_ssize_t` длиной [`ndim`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.ndim), задающий количество байтов, которое нужно пропустить, чтобы перейти к новому элементу в каждом измерении.9495Значения шага могут быть любыми целыми числами. Для обычных массивов шаги обычно положительны, но потребитель ДОЛЖЕН уметь обрабатывать случай `strides[n] <= 0`. Дополнительную информацию см. в разделе [сложные массивы](https://python-all.ru/3.5/c-api/buffer.html#complex-arrays).9697Массив шагов доступен потребителю только для чтения.9899**Py\_ssize\_t \*`suboffsets`**100101Массив из `Py_ssize_t` длиной [`ndim`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.ndim). Если `suboffsets[n] >= 0`, значения, хранящиеся по n-му измерению, являются указателями, и значение смещения подмассива указывает, сколько байтов добавить к каждому указателю после разыменования. Отрицательное значение смещения подмассива означает, что разыменование производиться не должно (шаг по непрерывному блоку памяти).102103Если все suboffsets отрицательны (т.е. разыменование не требуется), то это поле должно быть NULL (значение по умолчанию).104105Такой тип представления массива используется библиотекой Python Imaging Library (PIL). Дополнительную информацию о доступе к элементам такого массива см. в разделе [сложные массивы](https://python-all.ru/3.5/c-api/buffer.html#complex-arrays).106107Массив смещений подмассивов доступен потребителю только для чтения.108109**void \*`internal`**110111Предназначено для внутреннего использования экспортирующим объектом. Например, экспортёр может переинтерпретировать это значение как целое число и использовать для хранения флагов о том, нужно ли освобождать массивы shape, strides и suboffsets при освобождении буфера. Потребитель НЕ ДОЛЖЕН изменять это значение.112113## Типы запросов буфера114115Обычно буферы получают, отправляя запрос буфера экспортирующему объекту через [`PyObject_GetBuffer()`](https://python-all.ru/3.5/c-api/buffer.html#c.PyObject_GetBuffer). Поскольку сложность логической структуры памяти может сильно различаться, потребитель использует аргумент *flags* для указания точного типа буфера, с которым он может работать.116117Все поля [`Py_buffer`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer) однозначно определяются типом запроса.118119### поля, не зависящие от запроса120121Следующие поля не зависят от *flags* и всегда должны заполняться корректными значениями: [`obj`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.obj), [`buf`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.buf), [`len`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.len), [`itemsize`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.itemsize), [`ndim`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.ndim).122123### только для чтения, формат124125> **`PyBUF_WRITABLE`**126>127> Управляет полем [`readonly`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.readonly). Если флаг установлен, экспортёр ОБЯЗАН предоставить буфер для записи, иначе сообщить об ошибке. В противном случае экспортёр МОЖЕТ предоставить буфер только для чтения или для записи, но выбор ДОЛЖЕН быть единым для всех потребителей.128>129> **`PyBUF_FORMAT`**130>131> Управляет полем [`format`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.format). Если установлено, это поле ДОЛЖНО быть заполнено корректно. В противном случае это поле ДОЛЖНО быть *NULL*.132133[`PyBUF_WRITABLE`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBUF_WRITABLE) можно комбинировать (|) с любыми флагами из следующего раздела. Поскольку [`PyBUF_SIMPLE`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBUF_SIMPLE) определён как 0, [`PyBUF_WRITABLE`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBUF_WRITABLE) может использоваться как самостоятельный флаг для запроса простого буфера для записи.134135[`PyBUF_FORMAT`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBUF_FORMAT) можно комбинировать (по ИЛИ) с любыми флагами, кроме [`PyBUF_SIMPLE`](https://python-all.ru/3.5/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.5/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.5/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.5/c-api/buffer.html#c.Py_buffer.itemsize), [`ndim`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.ndim), [`shape`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.shape) и [`strides`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.strides).181182Если `ndim == 0`, область памяти, на которую указывает [`buf`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.buf), интерпретируется как скаляр размера [`itemsize`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.itemsize). В этом случае, оба [`shape`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.shape) и [`strides`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.strides) равны *NULL*.183184Если [`strides`](https://python-all.ru/3.5/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]`187>188> `item = *((typeof(item) *)ptr);`189190Как отмечалось выше, [`buf`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.buf) может указывать на любую позицию в реальном блоке памяти. Экспортер может проверить корректность буфера с помощью этой функции:191192```python193def verify_structure(memlen, itemsize, ndim, shape, strides, offset):194 """Проверить, что параметры представляют допустимый массив в пределах195 границ выделенной памяти:196 char *mem: начало физического блока памяти197 memlen: длина физического блока памяти198 смещение: (char *)buf - mem199 """200 if offset % itemsize:201 return False202 if offset < 0 or offset+itemsize > memlen:203 return False204 if any(v % itemsize for v in strides):205 return False206207 if ndim <= 0:208 return ndim == 0 and not shape and not strides209 if 0 in shape:210 return True211212 imin = sum(strides[j]*(shape[j]-1) for j in range(ndim)213 if strides[j] <= 0)214 imax = sum(strides[j]*(shape[j]-1) for j in range(ndim)215 if strides[j] > 0)216217 return 0 <= offset+imin and offset+imax+itemsize <= memlen218```219220### В стиле PIL: форма, шаги и suboffsets221222В дополнение к обычным элементам массивы в стиле PIL могут содержать указатели, по которым нужно перейти, чтобы получить следующий элемент в измерении. Например, обычный трехмерный C-массив `char v[2][2][3]` можно также рассматривать как массив из 2 указателей на 2 двумерных массива: `char (*v[2])[2][3]`. В представлении suboffsets эти два указателя могут быть встроены в начало [`buf`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.buf), указывая на два `char x[2][3]` массива, которые могут находиться в любом месте памяти.223224Ниже приведена функция, возвращающая указатель на элемент в N-мерном массиве, на который указывает N-мерный индекс, при наличии как ненулевых шагов (strides), так и субсмещений (suboffsets):225226```c227void *get_item_pointer(int ndim, void *buf, Py_ssize_t *strides,228 Py_ssize_t *suboffsets, Py_ssize_t *indices) {229 char *pointer = (char*)buf;230 int i;231 for (i = 0; i < ndim; i++) {232 pointer += strides[i] * indices[i];233 if (suboffsets[i] >=0 ) {234 pointer = *((char**)pointer) + suboffsets[i];235 }236 }237 return (void*)pointer;238}239```240241## Функции, связанные с буфером242243#### `int PyObject_CheckBuffer(PyObject *obj)`244245Возвращает `1`, если *obj* поддерживает буферный интерфейс, иначе `0`. Когда `1` возвращается, это не гарантирует, что [`PyObject_GetBuffer()`](https://python-all.ru/3.5/c-api/buffer.html#c.PyObject_GetBuffer) выполнится успешно.246247#### `int PyObject_GetBuffer(PyObject *exporter, Py_buffer *view, int flags)`248249Отправить запрос *экспортёру* на заполнение *представления* в соответствии с *флагами*. Если экспортёр не может предоставить буфер нужного типа, он ОБЯЗАН возбудить исключение `PyExc_BufferError`, установить `view->obj` в *NULL* и вернуть `-1`.250251В случае успеха заполняет *view*, устанавливает `view->obj` в новую ссылку на *exporter* и возвращает 0. В случае цепочечных поставщиков буфера, которые перенаправляют запросы одному объекту, `view->obj` МОЖЕТ ссылаться на этот объект вместо *exporter* (см. [Структуры буферных объектов](https://python-all.ru/3.5/c-api/typeobj.html#buffer-structs)).252253Успешные вызовы [`PyObject_GetBuffer()`](https://python-all.ru/3.5/c-api/buffer.html#c.PyObject_GetBuffer) должны быть парными с вызовами [`PyBuffer_Release()`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBuffer_Release), как и в случае с `malloc()` и `free()`. Таким образом, после того как потребитель закончил работу с буфером, [`PyBuffer_Release()`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBuffer_Release) должен быть вызван ровно один раз.254255#### `void PyBuffer_Release(Py_buffer *view)`256257Освобождает буфер *view* и уменьшает счётчик ссылок для `view->obj`. Эту функцию ОБЯЗАТЕЛЬНО нужно вызывать, когда буфер больше не используется, иначе могут возникнуть утечки ссылок.258259Вызов этой функции для буфера, который не был получен через [`PyObject_GetBuffer()`](https://python-all.ru/3.5/c-api/buffer.html#c.PyObject_GetBuffer), является ошибкой.260261#### `Py_ssize_t PyBuffer_SizeFromFormat(const char *)`262263Возвращает подразумеваемое [`itemsize`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.itemsize) из [`format`](https://python-all.ru/3.5/c-api/buffer.html#c.Py_buffer.format). Эта функция ещё не реализована.264265#### `int PyBuffer_IsContiguous(Py_buffer *view, char order)`266267Возвращает `1`, если память, определённая *view*, является C-стилем (*order* равно `'C'`) или Fortran-стилем (*order* равно `'F'`) [непрерывной](https://python-all.ru/3.5/glossary.html#term-contiguous) или любым из них (*order* равно `'A'`). В противном случае возвращает `0`.268269#### `void PyBuffer_FillContiguousStrides(int ndim, Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t itemsize, char order)`270271Заполняет массив *strides* шагами в байтах (byte-strides) для [непрерывного](https://python-all.ru/3.5/glossary.html#term-contiguous) массива заданной формы с заданным количеством байтов на элемент (в стиле C, если *order* равен `'C'`, или в стиле Fortran, если *order* равен `'F'`).272273#### `int PyBuffer_FillInfo(Py_buffer *view, PyObject *exporter, void *buf, Py_ssize_t len, int readonly, int flags)`274275Обрабатывает запросы буфера для экспортёра, который хочет предоставить *buf* размером *len* с настройкой возможности записи в соответствии с *readonly*. *buf* интерпретируется как последовательность байтов без знака.276277Аргумент *flags* указывает тип запроса. Эта функция всегда заполняет *view* в соответствии с флагами, за исключением случаев, когда *buf* помечен как доступный только для чтения и в *flags* установлен [`PyBUF_WRITABLE`](https://python-all.ru/3.5/c-api/buffer.html#c.PyBUF_WRITABLE).278279В случае успеха установить `view->obj` в новую ссылку на *экспортёр* и вернуть 0. В противном случае возбудить исключение `PyExc_BufferError`, установить `view->obj` в *NULL* и вернуть `-1`.280281Если эта функция используется как часть [getbufferproc](https://python-all.ru/3.5/c-api/typeobj.html#buffer-structs), *exporter* ДОЛЖЕН быть установлен на экспортирующий объект, а *flags* должны передаваться без изменений. В противном случае *exporter* ДОЛЖЕН быть NULL.282