Files
hustoj/web/python-docs/c-api/buffer.html
2025-03-09 17:10:56 +08:00

819 lines
71 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN">
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>缓冲协议 &#8212; Python 3.8.20 文档</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script src="../_static/translations.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="在 Python 3.8.20 文档 中搜索"
href="../_static/opensearch.xml"/>
<link rel="author" title="关于这些文档" href="../about.html" />
<link rel="index" title="索引" href="../genindex.html" />
<link rel="search" title="搜索" href="../search.html" />
<link rel="copyright" title="版权所有" href="../copyright.html" />
<link rel="next" title="旧缓冲协议" href="objbuffer.html" />
<link rel="prev" title="迭代器协议" href="iter.html" />
<link rel="canonical" href="https://docs.python.org/3/c-api/buffer.html" />
<style>
@media only screen {
table.full-width-table {
width: 100%;
}
}
</style>
<link rel="shortcut icon" type="image/png" href="../_static/py.svg" />
<script type="text/javascript" src="../_static/copybutton.js"></script>
<script type="text/javascript" src="../_static/menu.js"></script>
</head>
<body>
<div class="mobile-nav">
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu" />
<label for="menuToggler" class="toggler__label">
<span></span>
</label>
<nav class="nav-content" role="navigation">
<a href="https://www.python.org/" class="nav-logo">
<img src="../_static/py.svg" alt="Logo"/>
</a>
<div class="version_switcher_placeholder"></div>
<form role="search" class="search" action="../search.html" method="get">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
<path fill-rule="nonzero"
d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" fill="#444"></path>
</svg>
<input type="text" name="q" aria-label="快速搜索"/>
<input type="submit" value="转向"/>
</form>
</nav>
<div class="menu-wrapper">
<nav class="menu" role="navigation" aria-label="main navigation">
<div class="language_switcher_placeholder"></div>
<h3><a href="../contents.html">目录</a></h3>
<ul>
<li><a class="reference internal" href="#">缓冲协议</a><ul>
<li><a class="reference internal" href="#buffer-structure">缓冲区结构</a></li>
<li><a class="reference internal" href="#buffer-request-types">缓冲区请求的类型</a><ul>
<li><a class="reference internal" href="#request-independent-fields">与请求无关的字段</a></li>
<li><a class="reference internal" href="#readonly-format">只读,格式</a></li>
<li><a class="reference internal" href="#shape-strides-suboffsets">形状,步幅,子偏移量</a></li>
<li><a class="reference internal" href="#contiguity-requests">连续性的请求</a></li>
<li><a class="reference internal" href="#compound-requests">复合请求</a></li>
</ul>
</li>
<li><a class="reference internal" href="#complex-arrays">复杂数组</a><ul>
<li><a class="reference internal" href="#numpy-style-shape-and-strides">NumPy-风格:形状和步幅</a></li>
<li><a class="reference internal" href="#pil-style-shape-strides-and-suboffsets">PIL-风格:形状,步幅和子偏移量</a></li>
</ul>
</li>
<li><a class="reference internal" href="#buffer-related-functions">缓冲区相关函数</a></li>
</ul>
</li>
</ul>
<h4>上一个主题</h4>
<p class="topless"><a href="iter.html"
title="上一章">迭代器协议</a></p>
<h4>下一个主题</h4>
<p class="topless"><a href="objbuffer.html"
title="下一章">旧缓冲协议</a></p>
<div role="note" aria-label="source link">
<h3>本页</h3>
<ul class="this-page-menu">
<li><a href="../bugs.html">报告 Bug</a></li>
<li>
<a href="https://github.com/python/cpython/blob/3.8/Doc/c-api/buffer.rst"
rel="nofollow">显示源代码
</a>
</li>
</ul>
</div>
</nav>
</div>
</div>
<div id="outdated-warning" style="padding: .5em; text-align: center; background-color: #FFBABA; color: #6A0E0E;">
这个文档所针对的是一个已不再受支持的 Python 旧版本。
你应当升级版本,并阅读
<a href="/3/c-api/buffer.html"> Python 当前稳定版本的文档</a>.
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>导航</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="总目录"
accesskey="I">索引</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python 模块索引"
>模块</a> |</li>
<li class="right" >
<a href="objbuffer.html" title="旧缓冲协议"
accesskey="N">下一页</a> |</li>
<li class="right" >
<a href="iter.html" title="迭代器协议"
accesskey="P">上一页</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.8.20 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python/C API 参考手册</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="abstract.html" accesskey="U">抽象对象层</a> &#187;</li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
<input type="submit" value="转向" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
|
</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="buffer-protocol">
<span id="bufferobjects"></span><span id="index-0"></span><h1>缓冲协议<a class="headerlink" href="#buffer-protocol" title="永久链接至标题"></a></h1>
<p>在 Python 中可使用一些对象来包装对底层内存数组或称 <em>缓冲</em> 的访问。此类对象包括内置的 <a class="reference internal" href="../library/stdtypes.html#bytes" title="bytes"><code class="xref py py-class docutils literal notranslate"><span class="pre">bytes</span></code></a><a class="reference internal" href="../library/stdtypes.html#bytearray" title="bytearray"><code class="xref py py-class docutils literal notranslate"><span class="pre">bytearray</span></code></a> 以及一些如 <a class="reference internal" href="../library/array.html#array.array" title="array.array"><code class="xref py py-class docutils literal notranslate"><span class="pre">array.array</span></code></a> 这样的扩展类型。第三方库也可能会为了特殊的目的而定义它们自己的类型,例如用于图像处理和数值分析等。</p>
<p>虽然这些类型中的每一种都有自己的语义,但它们具有由可能较大的内存缓冲区支持的共同特征。 在某些情况下,希望直接访问该缓冲区而无需中间复制。</p>
<p>Python 以 <a class="reference internal" href="#bufferobjects"><span class="std std-ref">缓冲协议</span></a> 的形式在 C 层级上提供这样的功能。 此协议包括两个方面:</p>
<ul class="simple" id="index-1">
<li><p>在生产者这一方面,该类型的协议可以导出一个“缓冲区接口”,允许公开它的底层缓冲区信息。该接口的描述信息在 <a class="reference internal" href="typeobj.html#buffer-structs"><span class="std std-ref">缓冲区对象结构体</span></a> 一节中;</p></li>
<li><p>在消费者一侧,有几种方法可用于获得指向对象的原始底层数据的指针(例如一个方法的形参)。</p></li>
</ul>
<p>一些简单的对象例如 <a class="reference internal" href="../library/stdtypes.html#bytes" title="bytes"><code class="xref py py-class docutils literal notranslate"><span class="pre">bytes</span></code></a><a class="reference internal" href="../library/stdtypes.html#bytearray" title="bytearray"><code class="xref py py-class docutils literal notranslate"><span class="pre">bytearray</span></code></a> 会以面向字节的形式公开它们的底层缓冲区。 也可能会用其他形式;例如 <a class="reference internal" href="../library/array.html#array.array" title="array.array"><code class="xref py py-class docutils literal notranslate"><span class="pre">array.array</span></code></a> 所公开的元素可以是多字节值。</p>
<p>缓冲区接口的消费者的一个例子是文件对象的 <a class="reference internal" href="../library/io.html#io.BufferedIOBase.write" title="io.BufferedIOBase.write"><code class="xref py py-meth docutils literal notranslate"><span class="pre">write()</span></code></a> 方法:任何可以输出为一系列字节流的对象可以被写入文件。然而 <code class="xref py py-meth docutils literal notranslate"><span class="pre">write()</span></code> 方法只需要对于传入对象的只读权限,其他的方法,如 <a class="reference internal" href="../library/io.html#io.BufferedIOBase.readinto" title="io.BufferedIOBase.readinto"><code class="xref py py-meth docutils literal notranslate"><span class="pre">readinto()</span></code></a> 需要参数内容的写入权限。缓冲区接口使得对象可以选择性地允许或拒绝读写或只读缓冲区的导出。</p>
<p>对于缓冲区接口的使用者而言,有两种方式来获取一个目的对象的缓冲:</p>
<ul class="simple">
<li><p>使用正确的参数来调用 <a class="reference internal" href="#c.PyObject_GetBuffer" title="PyObject_GetBuffer"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_GetBuffer()</span></code></a> 函数;</p></li>
<li><p>调用 <a class="reference internal" href="arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a> (或其同级对象之一) 并传入 <code class="docutils literal notranslate"><span class="pre">y*</span></code>, <code class="docutils literal notranslate"><span class="pre">w*</span></code> or <code class="docutils literal notranslate"><span class="pre">s*</span></code> <a class="reference internal" href="arg.html#arg-parsing"><span class="std std-ref">格式代码</span></a> 中的一个。</p></li>
</ul>
<p>在这两种情况下,当不再需要缓冲区时必须调用 <a class="reference internal" href="#c.PyBuffer_Release" title="PyBuffer_Release"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyBuffer_Release()</span></code></a> 。如果此操作失败,可能会导致各种问题,例如资源泄漏。</p>
<section id="buffer-structure">
<span id="id1"></span><h2>缓冲区结构<a class="headerlink" href="#buffer-structure" title="永久链接至标题"></a></h2>
<p>缓冲区结构(或者简单地称为“buffers”)对于将二进制数据从另一个对象公开给 Python 程序员非常有用。它们还可以用作零拷贝切片机制。使用它们引用内存块的能力,可以很容易地将任何数据公开给 Python 程序员。内存可以是 C 扩展中的一个大的常量数组,也可以是在传递到操作系统库之前用于操作的原始内存块,或者可以用来传递本机内存格式的结构化数据。</p>
<p>与 Python 解释器公开的大多部数据类型不同,缓冲区不是 <a class="reference internal" href="structures.html#c.PyObject" title="PyObject"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyObject</span></code></a> 指针而是简单的 C 结构。 这使得它们可以非常简单地创建和复制。 当需要为缓冲区加上泛型包装器时,可以创建一个 <a class="reference internal" href="memoryview.html#memoryview-objects"><span class="std std-ref">内存视图</span></a> 对象。</p>
<p>有关如何编写并导出对象的简短说明,请参阅 <a class="reference internal" href="typeobj.html#buffer-structs"><span class="std std-ref">缓冲区对象结构</span></a>。 要获取缓冲区对象,请参阅 <a class="reference internal" href="#c.PyObject_GetBuffer" title="PyObject_GetBuffer"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_GetBuffer()</span></code></a></p>
<dl class="type">
<dt id="c.Py_buffer">
<code class="sig-name descname">Py_buffer</code><a class="headerlink" href="#c.Py_buffer" title="永久链接至目标"></a></dt>
<dd><dl class="member">
<dt id="c.Py_buffer.buf">
void *<code class="sig-name descname">buf</code><a class="headerlink" href="#c.Py_buffer.buf" title="永久链接至目标"></a></dt>
<dd><p>指向由缓冲区字段描述的逻辑结构开始的指针。 这可以是导出程序底层物理内存块中的任何位置。 例如,使用负的 <a class="reference internal" href="#c.Py_buffer.strides" title="Py_buffer.strides"><code class="xref c c-member docutils literal notranslate"><span class="pre">strides</span></code></a> 值可能指向内存块的末尾。</p>
<p>对于 <a class="reference internal" href="../glossary.html#term-contiguous"><span class="xref std std-term">contiguous</span></a> ,‘邻接’数组,值指向内存块的开头。</p>
</dd></dl>
<dl class="member">
<dt id="c.Py_buffer.obj">
void *<code class="sig-name descname">obj</code><a class="headerlink" href="#c.Py_buffer.obj" title="永久链接至目标"></a></dt>
<dd><p>对导出对象的新引用。 该引用归使用者所有,并由 <a class="reference internal" href="#c.PyBuffer_Release" title="PyBuffer_Release"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyBuffer_Release()</span></code></a> 自动递减并设置为 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>。 该字段等于任何标准 C-API 函数的返回值。</p>
<p>作为一种特殊情况,对于由 <a class="reference internal" href="memoryview.html#c.PyMemoryView_FromBuffer" title="PyMemoryView_FromBuffer"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMemoryView_FromBuffer()</span></code></a><a class="reference internal" href="#c.PyBuffer_FillInfo" title="PyBuffer_FillInfo"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyBuffer_FillInfo()</span></code></a> 包装的 <em>temporary</em> 缓冲区,此字段为 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>。 通常,导出对象不得使用此方案。</p>
</dd></dl>
<dl class="member">
<dt id="c.Py_buffer.len">
Py_ssize_t <code class="sig-name descname">len</code><a class="headerlink" href="#c.Py_buffer.len" title="永久链接至目标"></a></dt>
<dd><p><code class="docutils literal notranslate"><span class="pre">product(shape)</span> <span class="pre">*</span> <span class="pre">itemsize</span></code>。对于连续数组,这是基础内存块的长度。对于非连续数组,如果逻辑结构复制到连续表示形式,则该长度将具有该长度。</p>
<p>仅当缓冲区是通过保证连续性的请求获取时,才访问 <code class="docutils literal notranslate"><span class="pre">((char</span> <span class="pre">*)buf)[0]</span> <span class="pre">up</span> <span class="pre">to</span> <span class="pre">((char</span> <span class="pre">*)buf)[len-1]</span></code> 时才有效。在大多数情况下,此类请求将为 <a class="reference internal" href="#c.PyBUF_SIMPLE" title="PyBUF_SIMPLE"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_SIMPLE</span></code></a><a class="reference internal" href="#c.PyBUF_WRITABLE" title="PyBUF_WRITABLE"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_WRITABLE</span></code></a></p>
</dd></dl>
<dl class="member">
<dt id="c.Py_buffer.readonly">
int <code class="sig-name descname">readonly</code><a class="headerlink" href="#c.Py_buffer.readonly" title="永久链接至目标"></a></dt>
<dd><p>缓冲区是否为只读的指示器。此字段由 <a class="reference internal" href="#c.PyBUF_WRITABLE" title="PyBUF_WRITABLE"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_WRITABLE</span></code></a> 标志控制。</p>
</dd></dl>
<dl class="member">
<dt id="c.Py_buffer.itemsize">
Py_ssize_t <code class="sig-name descname">itemsize</code><a class="headerlink" href="#c.Py_buffer.itemsize" title="永久链接至目标"></a></dt>
<dd><p>单个元素的项大小(以字节为单位)。与 <a class="reference internal" href="../library/struct.html#struct.calcsize" title="struct.calcsize"><code class="xref py py-func docutils literal notranslate"><span class="pre">struct.calcsize()</span></code></a> 调用非 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> <a class="reference internal" href="#c.Py_buffer.format" title="Py_buffer.format"><code class="xref c c-member docutils literal notranslate"><span class="pre">format</span></code></a> 的值相同。</p>
<p>重要例外:如果使用者请求的缓冲区没有 <a class="reference internal" href="#c.PyBUF_FORMAT" title="PyBUF_FORMAT"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_FORMAT</span></code></a> 标志,<a class="reference internal" href="#c.Py_buffer.format" title="Py_buffer.format"><code class="xref c c-member docutils literal notranslate"><span class="pre">format</span></code></a> 将设置为 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>,但 <a class="reference internal" href="#c.Py_buffer.itemsize" title="Py_buffer.itemsize"><code class="xref c c-member docutils literal notranslate"><span class="pre">itemsize</span></code></a> 仍具有原始格式的值。</p>
<p>如果 <a class="reference internal" href="#c.Py_buffer.shape" title="Py_buffer.shape"><code class="xref c c-member docutils literal notranslate"><span class="pre">shape</span></code></a> 存在,则相等的 <code class="docutils literal notranslate"><span class="pre">product(shape)</span> <span class="pre">*</span> <span class="pre">itemsize</span> <span class="pre">==</span> <span class="pre">len</span></code> 仍然存在,使用者可以使用 <a class="reference internal" href="#c.Py_buffer.itemsize" title="Py_buffer.itemsize"><code class="xref c c-member docutils literal notranslate"><span class="pre">itemsize</span></code></a> 来导航缓冲区。</p>
<p>如果 <a class="reference internal" href="#c.Py_buffer.shape" title="Py_buffer.shape"><code class="xref c c-member docutils literal notranslate"><span class="pre">shape</span></code></a><code class="docutils literal notranslate"><span class="pre">NULL</span></code>,因为结果为 <a class="reference internal" href="#c.PyBUF_SIMPLE" title="PyBUF_SIMPLE"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_SIMPLE</span></code></a><a class="reference internal" href="#c.PyBUF_WRITABLE" title="PyBUF_WRITABLE"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_WRITABLE</span></code></a> 请求,则使用者必须忽略 <a class="reference internal" href="#c.Py_buffer.itemsize" title="Py_buffer.itemsize"><code class="xref c c-member docutils literal notranslate"><span class="pre">itemsize</span></code></a>,并假设 <code class="docutils literal notranslate"><span class="pre">itemsize</span> <span class="pre">==</span> <span class="pre">1</span></code></p>
</dd></dl>
<dl class="member">
<dt id="c.Py_buffer.format">
const char *<code class="sig-name descname">format</code><a class="headerlink" href="#c.Py_buffer.format" title="永久链接至目标"></a></dt>
<dd><p><a class="reference internal" href="../library/struct.html#module-struct" title="struct: Interpret bytes as packed binary data."><code class="xref py py-mod docutils literal notranslate"><span class="pre">struct</span></code></a> 模块样式语法中 <em>NUL</em> 字符串,描述单个项的内容。如果这是 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>,则假定为 <code class="docutils literal notranslate"><span class="pre">&quot;B&quot;</span></code> (无符号字节) 。</p>
<p>此字段由 <a class="reference internal" href="#c.PyBUF_FORMAT" title="PyBUF_FORMAT"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_FORMAT</span></code></a> 标志控制。</p>
</dd></dl>
<dl class="member">
<dt id="c.Py_buffer.ndim">
int <code class="sig-name descname">ndim</code><a class="headerlink" href="#c.Py_buffer.ndim" title="永久链接至目标"></a></dt>
<dd><p>内存表示为 n 维数组的维数。 如果是 <code class="docutils literal notranslate"><span class="pre">0</span></code> <a class="reference internal" href="#c.Py_buffer.buf" title="Py_buffer.buf"><code class="xref c c-member docutils literal notranslate"><span class="pre">buf</span></code></a> 指向表示标量的单个项目。 在这种情况下,<a class="reference internal" href="#c.Py_buffer.shape" title="Py_buffer.shape"><code class="xref c c-member docutils literal notranslate"><span class="pre">shape</span></code></a><a class="reference internal" href="#c.Py_buffer.strides" title="Py_buffer.strides"><code class="xref c c-member docutils literal notranslate"><span class="pre">strides</span></code></a><a class="reference internal" href="#c.Py_buffer.suboffsets" title="Py_buffer.suboffsets"><code class="xref c c-member docutils literal notranslate"><span class="pre">suboffsets</span></code></a> 必须是 <code class="docutils literal notranslate"><span class="pre">NULL</span></code></p>
<p><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_MAX_NDIM</span></code> 将最大维度数限制为 64。 导出程序必须遵守这个限制,多维缓冲区的使用者应该能够处理最多 <code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_MAX_NDIM</span></code> 维度。</p>
</dd></dl>
<dl class="member">
<dt id="c.Py_buffer.shape">
Py_ssize_t *<code class="sig-name descname">shape</code><a class="headerlink" href="#c.Py_buffer.shape" title="永久链接至目标"></a></dt>
<dd><p>一个长度为 <code class="xref c c-type docutils literal notranslate"><span class="pre">Py_ssize_t</span></code> 的数组 <a class="reference internal" href="#c.Py_buffer.ndim" title="Py_buffer.ndim"><code class="xref c c-member docutils literal notranslate"><span class="pre">ndim</span></code></a> 表示作为 n 维数组的内存形状。 请注意,<code class="docutils literal notranslate"><span class="pre">shape[0]</span> <span class="pre">*</span> <span class="pre">...</span> <span class="pre">*</span> <span class="pre">shape[ndim-1]</span> <span class="pre">*</span> <span class="pre">itemsize</span></code> 必须等于 <a class="reference internal" href="#c.Py_buffer.len" title="Py_buffer.len"><code class="xref c c-member docutils literal notranslate"><span class="pre">len</span></code></a></p>
<p>Shape 形状数组中的值被限定在 <code class="docutils literal notranslate"><span class="pre">shape[n]</span> <span class="pre">&gt;=</span> <span class="pre">0</span></code><code class="docutils literal notranslate"><span class="pre">shape[n]</span> <span class="pre">==</span> <span class="pre">0</span></code> 这一情形需要特别注意。更多信息请参阅 <a class="reference internal" href="#complex-arrays">complex arrays</a></p>
<p>shape 数组对于使用者来说是只读的。</p>
</dd></dl>
<dl class="member">
<dt id="c.Py_buffer.strides">
Py_ssize_t *<code class="sig-name descname">strides</code><a class="headerlink" href="#c.Py_buffer.strides" title="永久链接至目标"></a></dt>
<dd><p>一个长度为 <code class="xref c c-type docutils literal notranslate"><span class="pre">Py_ssize_t</span></code> 的数组 <a class="reference internal" href="#c.Py_buffer.ndim" title="Py_buffer.ndim"><code class="xref c c-member docutils literal notranslate"><span class="pre">ndim</span></code></a> 给出要跳过的字节数以获取每个尺寸中的新元素。</p>
<p>Stride 步幅数组中的值可以为任何整数。对于常规数组,步幅通常为正数,但是使用者必须能够处理 <code class="docutils literal notranslate"><span class="pre">strides[n]</span> <span class="pre">&lt;=</span> <span class="pre">0</span></code> 的情况。更多信息请参阅 <a class="reference internal" href="#complex-arrays">complex arrays</a></p>
<p>strides数组对用户来说是只读的。</p>
</dd></dl>
<dl class="member">
<dt id="c.Py_buffer.suboffsets">
Py_ssize_t *<code class="sig-name descname">suboffsets</code><a class="headerlink" href="#c.Py_buffer.suboffsets" title="永久链接至目标"></a></dt>
<dd><p>一个长度为 <a class="reference internal" href="#c.Py_buffer.ndim" title="Py_buffer.ndim"><code class="xref c c-member docutils literal notranslate"><span class="pre">ndim</span></code></a> 类型为 <code class="xref c c-type docutils literal notranslate"><span class="pre">Py_ssize_t</span></code> 的数组 。如果 <code class="docutils literal notranslate"><span class="pre">suboffsets[n]</span> <span class="pre">&gt;=</span> <span class="pre">0</span></code>,则第 n 维存储的是指针suboffset 值决定了解除引用时要给指针增加多少字节的偏移。suboffset 为负值,则表示不应解除引用(在连续内存块中移动)。</p>
<p>如果所有子偏移均为负(即无需取消引用),则此字段必须为 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> (默认值)。</p>
<p>Python Imaging Library (PIL) 中使用了这种类型的数组表达方式。请参阅 <a class="reference internal" href="#complex-arrays">complex arrays</a> 来了解如何从这样一个数组中访问元素。</p>
<p>suboffsets 数组对于使用者来说是只读的。</p>
</dd></dl>
<dl class="member">
<dt id="c.Py_buffer.internal">
void *<code class="sig-name descname">internal</code><a class="headerlink" href="#c.Py_buffer.internal" title="永久链接至目标"></a></dt>
<dd><p>供输出对象内部使用。比如可能被输出程序重组为一个整数,用于存储一个标志,标明在缓冲区释放时是否必须释放 shape、strides 和 suboffsets 数组。消费者程序 <em>不得</em> 修改该值。</p>
</dd></dl>
</dd></dl>
</section>
<section id="buffer-request-types">
<span id="id2"></span><h2>缓冲区请求的类型<a class="headerlink" href="#buffer-request-types" title="永久链接至标题"></a></h2>
<p>通常,通过 <a class="reference internal" href="#c.PyObject_GetBuffer" title="PyObject_GetBuffer"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_GetBuffer()</span></code></a> 向输出对象发送缓冲区请求,即可获得缓冲区。由于内存的逻辑结构复杂,可能会有很大差异,缓冲区使用者可用 <em>flags</em> 参数指定其能够处理的缓冲区具体类型。</p>
<p>所有 <a class="reference internal" href="#c.Py_buffer" title="Py_buffer"><code class="xref c c-data docutils literal notranslate"><span class="pre">Py_buffer</span></code></a> 字段均由请求类型明确定义。</p>
<section id="request-independent-fields">
<h3>与请求无关的字段<a class="headerlink" href="#request-independent-fields" title="永久链接至标题"></a></h3>
<p>以下字段不会被 <em>flags</em> 影响,并且必须总是用正确的值填充:<a class="reference internal" href="#c.Py_buffer.obj" title="Py_buffer.obj"><code class="xref c c-member docutils literal notranslate"><span class="pre">obj</span></code></a>, <a class="reference internal" href="#c.Py_buffer.buf" title="Py_buffer.buf"><code class="xref c c-member docutils literal notranslate"><span class="pre">buf</span></code></a><a class="reference internal" href="#c.Py_buffer.len" title="Py_buffer.len"><code class="xref c c-member docutils literal notranslate"><span class="pre">len</span></code></a><a class="reference internal" href="#c.Py_buffer.itemsize" title="Py_buffer.itemsize"><code class="xref c c-member docutils literal notranslate"><span class="pre">itemsize</span></code></a><a class="reference internal" href="#c.Py_buffer.ndim" title="Py_buffer.ndim"><code class="xref c c-member docutils literal notranslate"><span class="pre">ndim</span></code></a></p>
</section>
<section id="readonly-format">
<h3>只读,格式<a class="headerlink" href="#readonly-format" title="永久链接至标题"></a></h3>
<blockquote>
<div><dl class="macro">
<dt id="c.PyBUF_WRITABLE">
<code class="sig-name descname">PyBUF_WRITABLE</code><a class="headerlink" href="#c.PyBUF_WRITABLE" title="永久链接至目标"></a></dt>
<dd><p>控制 <a class="reference internal" href="#c.Py_buffer.readonly" title="Py_buffer.readonly"><code class="xref c c-member docutils literal notranslate"><span class="pre">readonly</span></code></a> 字段。如果设置了,输出程序 <em>必须</em> 提供一个可写的缓冲区,否则报告失败。若未设置,输出程序 <em>可以</em> 提供只读或可写的缓冲区,但对所有消费者程序 <em>必须</em> 保持一致。</p>
</dd></dl>
<dl class="macro">
<dt id="c.PyBUF_FORMAT">
<code class="sig-name descname">PyBUF_FORMAT</code><a class="headerlink" href="#c.PyBUF_FORMAT" title="永久链接至目标"></a></dt>
<dd><p>控制 <a class="reference internal" href="#c.Py_buffer.format" title="Py_buffer.format"><code class="xref c c-member docutils literal notranslate"><span class="pre">format</span></code></a> 字段。 如果设置,则必须正确填写此字段。其他情况下,此字段必须为 <code class="docutils literal notranslate"><span class="pre">NULL</span></code></p>
</dd></dl>
</div></blockquote>
<p><a class="reference internal" href="#c.PyBUF_WRITABLE" title="PyBUF_WRITABLE"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_WRITABLE</span></code></a> 可以和下一节的所有标志联用。由于 <a class="reference internal" href="#c.PyBUF_SIMPLE" title="PyBUF_SIMPLE"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_SIMPLE</span></code></a> 定义为 0所以 <a class="reference internal" href="#c.PyBUF_WRITABLE" title="PyBUF_WRITABLE"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_WRITABLE</span></code></a> 可以作为一个独立的标志,用于请求一个简单的可写缓冲区。</p>
<p><a class="reference internal" href="#c.PyBUF_FORMAT" title="PyBUF_FORMAT"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_FORMAT</span></code></a> 可以被设为除了 <a class="reference internal" href="#c.PyBUF_SIMPLE" title="PyBUF_SIMPLE"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_SIMPLE</span></code></a> 之外的任何标志。 后者已经按暗示了 <code class="docutils literal notranslate"><span class="pre">B</span></code> (无符号字节串)格式。</p>
</section>
<section id="shape-strides-suboffsets">
<h3>形状,步幅,子偏移量<a class="headerlink" href="#shape-strides-suboffsets" title="永久链接至标题"></a></h3>
<p>控制内存逻辑结构的标志按照复杂度的递减顺序列出。注意,每个标志包含它下面的所有标志。</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 51%" />
<col style="width: 12%" />
<col style="width: 16%" />
<col style="width: 21%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>请求</p></th>
<th class="head"><p>形状</p></th>
<th class="head"><p>步幅</p></th>
<th class="head"><p>子偏移量</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><dl class="macro">
<dt id="c.PyBUF_INDIRECT">
<code class="sig-name descname">PyBUF_INDIRECT</code><a class="headerlink" href="#c.PyBUF_INDIRECT" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p></p></td>
<td><p></p></td>
<td><p>如果需要的话</p></td>
</tr>
<tr class="row-odd"><td><dl class="macro">
<dt id="c.PyBUF_STRIDES">
<code class="sig-name descname">PyBUF_STRIDES</code><a class="headerlink" href="#c.PyBUF_STRIDES" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p></p></td>
<td><p></p></td>
<td><p>NULL</p></td>
</tr>
<tr class="row-even"><td><dl class="macro">
<dt id="c.PyBUF_ND">
<code class="sig-name descname">PyBUF_ND</code><a class="headerlink" href="#c.PyBUF_ND" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p></p></td>
<td><p>NULL</p></td>
<td><p>NULL</p></td>
</tr>
<tr class="row-odd"><td><dl class="macro">
<dt id="c.PyBUF_SIMPLE">
<code class="sig-name descname">PyBUF_SIMPLE</code><a class="headerlink" href="#c.PyBUF_SIMPLE" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p>NULL</p></td>
<td><p>NULL</p></td>
<td><p>NULL</p></td>
</tr>
</tbody>
</table>
</section>
<section id="contiguity-requests">
<span id="index-2"></span><h3>连续性的请求<a class="headerlink" href="#contiguity-requests" title="永久链接至标题"></a></h3>
<p>可以显式地请求C 或 Fortran <a class="reference internal" href="../glossary.html#term-contiguous"><span class="xref std std-term">连续</span></a> ,不管有没有步幅信息。若没有步幅信息,则缓冲区必须是 C-连续的。</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 49%" />
<col style="width: 10%" />
<col style="width: 13%" />
<col style="width: 17%" />
<col style="width: 11%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>请求</p></th>
<th class="head"><p>形状</p></th>
<th class="head"><p>步幅</p></th>
<th class="head"><p>子偏移量</p></th>
<th class="head"><p>邻接</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><dl class="macro">
<dt id="c.PyBUF_C_CONTIGUOUS">
<code class="sig-name descname">PyBUF_C_CONTIGUOUS</code><a class="headerlink" href="#c.PyBUF_C_CONTIGUOUS" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p></p></td>
<td><p></p></td>
<td><p>NULL</p></td>
<td><p>C</p></td>
</tr>
<tr class="row-odd"><td><dl class="macro">
<dt id="c.PyBUF_F_CONTIGUOUS">
<code class="sig-name descname">PyBUF_F_CONTIGUOUS</code><a class="headerlink" href="#c.PyBUF_F_CONTIGUOUS" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p></p></td>
<td><p></p></td>
<td><p>NULL</p></td>
<td><p>F</p></td>
</tr>
<tr class="row-even"><td><dl class="macro">
<dt id="c.PyBUF_ANY_CONTIGUOUS">
<code class="sig-name descname">PyBUF_ANY_CONTIGUOUS</code><a class="headerlink" href="#c.PyBUF_ANY_CONTIGUOUS" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p></p></td>
<td><p></p></td>
<td><p>NULL</p></td>
<td><p>C 或 F</p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="#c.PyBUF_ND" title="PyBUF_ND"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_ND</span></code></a></p></td>
<td><p></p></td>
<td><p>NULL</p></td>
<td><p>NULL</p></td>
<td><p>C</p></td>
</tr>
</tbody>
</table>
</section>
<section id="compound-requests">
<h3>复合请求<a class="headerlink" href="#compound-requests" title="永久链接至标题"></a></h3>
<p>所有可能的请求都由上一节中某些标志的组合完全定义。为方便起见,缓冲区协议提供常用的组合作为单个标志。</p>
<p>在下表中,<em>U</em> 代表连续性未定义。消费者程序必须调用 <a class="reference internal" href="#c.PyBuffer_IsContiguous" title="PyBuffer_IsContiguous"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyBuffer_IsContiguous()</span></code></a> 以确定连续性。</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 36%" />
<col style="width: 8%" />
<col style="width: 11%" />
<col style="width: 14%" />
<col style="width: 9%" />
<col style="width: 12%" />
<col style="width: 9%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>请求</p></th>
<th class="head"><p>形状</p></th>
<th class="head"><p>步幅</p></th>
<th class="head"><p>子偏移量</p></th>
<th class="head"><p>邻接</p></th>
<th class="head"><p>readonly</p></th>
<th class="head"><p>format</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><dl class="macro">
<dt id="c.PyBUF_FULL">
<code class="sig-name descname">PyBUF_FULL</code><a class="headerlink" href="#c.PyBUF_FULL" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p></p></td>
<td><p></p></td>
<td><p>如果需要的话</p></td>
<td><p>U</p></td>
<td><p>0</p></td>
<td><p></p></td>
</tr>
<tr class="row-odd"><td><dl class="macro">
<dt id="c.PyBUF_FULL_RO">
<code class="sig-name descname">PyBUF_FULL_RO</code><a class="headerlink" href="#c.PyBUF_FULL_RO" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p></p></td>
<td><p></p></td>
<td><p>如果需要的话</p></td>
<td><p>U</p></td>
<td><p>1 或 0</p></td>
<td><p></p></td>
</tr>
<tr class="row-even"><td><dl class="macro">
<dt id="c.PyBUF_RECORDS">
<code class="sig-name descname">PyBUF_RECORDS</code><a class="headerlink" href="#c.PyBUF_RECORDS" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p></p></td>
<td><p></p></td>
<td><p>NULL</p></td>
<td><p>U</p></td>
<td><p>0</p></td>
<td><p></p></td>
</tr>
<tr class="row-odd"><td><dl class="macro">
<dt id="c.PyBUF_RECORDS_RO">
<code class="sig-name descname">PyBUF_RECORDS_RO</code><a class="headerlink" href="#c.PyBUF_RECORDS_RO" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p></p></td>
<td><p></p></td>
<td><p>NULL</p></td>
<td><p>U</p></td>
<td><p>1 或 0</p></td>
<td><p></p></td>
</tr>
<tr class="row-even"><td><dl class="macro">
<dt id="c.PyBUF_STRIDED">
<code class="sig-name descname">PyBUF_STRIDED</code><a class="headerlink" href="#c.PyBUF_STRIDED" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p></p></td>
<td><p></p></td>
<td><p>NULL</p></td>
<td><p>U</p></td>
<td><p>0</p></td>
<td><p>NULL</p></td>
</tr>
<tr class="row-odd"><td><dl class="macro">
<dt id="c.PyBUF_STRIDED_RO">
<code class="sig-name descname">PyBUF_STRIDED_RO</code><a class="headerlink" href="#c.PyBUF_STRIDED_RO" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p></p></td>
<td><p></p></td>
<td><p>NULL</p></td>
<td><p>U</p></td>
<td><p>1 或 0</p></td>
<td><p>NULL</p></td>
</tr>
<tr class="row-even"><td><dl class="macro">
<dt id="c.PyBUF_CONTIG">
<code class="sig-name descname">PyBUF_CONTIG</code><a class="headerlink" href="#c.PyBUF_CONTIG" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p></p></td>
<td><p>NULL</p></td>
<td><p>NULL</p></td>
<td><p>C</p></td>
<td><p>0</p></td>
<td><p>NULL</p></td>
</tr>
<tr class="row-odd"><td><dl class="macro">
<dt id="c.PyBUF_CONTIG_RO">
<code class="sig-name descname">PyBUF_CONTIG_RO</code><a class="headerlink" href="#c.PyBUF_CONTIG_RO" title="永久链接至目标"></a></dt>
<dd></dd></dl>
</td>
<td><p></p></td>
<td><p>NULL</p></td>
<td><p>NULL</p></td>
<td><p>C</p></td>
<td><p>1 或 0</p></td>
<td><p>NULL</p></td>
</tr>
</tbody>
</table>
</section>
</section>
<section id="complex-arrays">
<h2>复杂数组<a class="headerlink" href="#complex-arrays" title="永久链接至标题"></a></h2>
<section id="numpy-style-shape-and-strides">
<h3>NumPy-风格:形状和步幅<a class="headerlink" href="#numpy-style-shape-and-strides" title="永久链接至标题"></a></h3>
<p>NumPy 风格数组的逻辑结构由 <a class="reference internal" href="#c.Py_buffer.itemsize" title="Py_buffer.itemsize"><code class="xref c c-member docutils literal notranslate"><span class="pre">itemsize</span></code></a><a class="reference internal" href="#c.Py_buffer.ndim" title="Py_buffer.ndim"><code class="xref c c-member docutils literal notranslate"><span class="pre">ndim</span></code></a><a class="reference internal" href="#c.Py_buffer.shape" title="Py_buffer.shape"><code class="xref c c-member docutils literal notranslate"><span class="pre">shape</span></code></a><a class="reference internal" href="#c.Py_buffer.strides" title="Py_buffer.strides"><code class="xref c c-member docutils literal notranslate"><span class="pre">strides</span></code></a> 定义。</p>
<p>如果 <code class="docutils literal notranslate"><span class="pre">ndim</span> <span class="pre">==</span> <span class="pre">0</span></code> <a class="reference internal" href="#c.Py_buffer.buf" title="Py_buffer.buf"><code class="xref c c-member docutils literal notranslate"><span class="pre">buf</span></code></a> 指向的内存位置被解释为大小为 <a class="reference internal" href="#c.Py_buffer.itemsize" title="Py_buffer.itemsize"><code class="xref c c-member docutils literal notranslate"><span class="pre">itemsize</span></code></a> 的标量。这时, <a class="reference internal" href="#c.Py_buffer.shape" title="Py_buffer.shape"><code class="xref c c-member docutils literal notranslate"><span class="pre">shape</span></code></a><a class="reference internal" href="#c.Py_buffer.strides" title="Py_buffer.strides"><code class="xref c c-member docutils literal notranslate"><span class="pre">strides</span></code></a> 都为 <code class="docutils literal notranslate"><span class="pre">NULL</span></code></p>
<p>如果 <a class="reference internal" href="#c.Py_buffer.strides" title="Py_buffer.strides"><code class="xref c c-member docutils literal notranslate"><span class="pre">strides</span></code></a><code class="docutils literal notranslate"><span class="pre">NULL</span></code>,则数组将被解释为一个标准的 n 维 C 语言数组。否则,消费者程序必须按如下方式访问 n 维数组:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">ptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="n">buf</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">indices</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">strides</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">indices</span><span class="p">[</span><span class="n">n</span><span class="mi">-1</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">strides</span><span class="p">[</span><span class="n">n</span><span class="mi">-1</span><span class="p">];</span>
<span class="n">item</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">*</span><span class="p">((</span><span class="n">typeof</span><span class="p">(</span><span class="n">item</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="n">ptr</span><span class="p">);</span>
</pre></div>
</div>
<p>如上所述,<a class="reference internal" href="#c.Py_buffer.buf" title="Py_buffer.buf"><code class="xref c c-member docutils literal notranslate"><span class="pre">buf</span></code></a> 可以指向实际内存块中的任意位置。输出者程序可以用该函数检查缓冲区的有效性。</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">verify_structure</span><span class="p">(</span><span class="n">memlen</span><span class="p">,</span> <span class="n">itemsize</span><span class="p">,</span> <span class="n">ndim</span><span class="p">,</span> <span class="n">shape</span><span class="p">,</span> <span class="n">strides</span><span class="p">,</span> <span class="n">offset</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Verify that the parameters represent a valid array within</span>
<span class="sd"> the bounds of the allocated memory:</span>
<span class="sd"> char *mem: start of the physical memory block</span>
<span class="sd"> memlen: length of the physical memory block</span>
<span class="sd"> offset: (char *)buf - mem</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">offset</span> <span class="o">%</span> <span class="n">itemsize</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">if</span> <span class="n">offset</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">offset</span><span class="o">+</span><span class="n">itemsize</span> <span class="o">&gt;</span> <span class="n">memlen</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">if</span> <span class="nb">any</span><span class="p">(</span><span class="n">v</span> <span class="o">%</span> <span class="n">itemsize</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">strides</span><span class="p">):</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">if</span> <span class="n">ndim</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="n">ndim</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">shape</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">strides</span>
<span class="k">if</span> <span class="mi">0</span> <span class="ow">in</span> <span class="n">shape</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">True</span>
<span class="n">imin</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">strides</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">*</span><span class="p">(</span><span class="n">shape</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">ndim</span><span class="p">)</span>
<span class="k">if</span> <span class="n">strides</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">imax</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">strides</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">*</span><span class="p">(</span><span class="n">shape</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">ndim</span><span class="p">)</span>
<span class="k">if</span> <span class="n">strides</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">return</span> <span class="mi">0</span> <span class="o">&lt;=</span> <span class="n">offset</span><span class="o">+</span><span class="n">imin</span> <span class="ow">and</span> <span class="n">offset</span><span class="o">+</span><span class="n">imax</span><span class="o">+</span><span class="n">itemsize</span> <span class="o">&lt;=</span> <span class="n">memlen</span>
</pre></div>
</div>
</section>
<section id="pil-style-shape-strides-and-suboffsets">
<h3>PIL-风格:形状,步幅和子偏移量<a class="headerlink" href="#pil-style-shape-strides-and-suboffsets" title="永久链接至标题"></a></h3>
<p>除了常规项之外, PIL 风格的数组还可以包含指针,必须跟随这些指针才能到达维度的下一个元素。例如,常规的三维 C 语言数组 <code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">v[2][2][3]</span></code> 可以看作是一个指向 2 个二维数组的 2 个指针:<code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">(*v[2])[2][3]</span></code>。在子偏移表示中,这两个指针可以嵌入在 <a class="reference internal" href="#c.Py_buffer.buf" title="Py_buffer.buf"><code class="xref c c-member docutils literal notranslate"><span class="pre">buf</span></code></a> 的开头,指向两个可以位于内存任何位置的 <code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">x[2][3]</span></code> 数组。</p>
<p>这是一个函数当n维索引所指向的N-D数组中有 <code class="docutils literal notranslate"><span class="pre">NULL</span></code> 步长和子偏移量时,它返回一个指针</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="kt">void</span><span class="w"> </span><span class="o">*</span><span class="nf">get_item_pointer</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">ndim</span><span class="p">,</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="o">*</span><span class="n">buf</span><span class="p">,</span><span class="w"> </span><span class="n">Py_ssize_t</span><span class="w"> </span><span class="o">*</span><span class="n">strides</span><span class="p">,</span>
<span class="w"> </span><span class="n">Py_ssize_t</span><span class="w"> </span><span class="o">*</span><span class="n">suboffsets</span><span class="p">,</span><span class="w"> </span><span class="n">Py_ssize_t</span><span class="w"> </span><span class="o">*</span><span class="n">indices</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">pointer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="kt">char</span><span class="o">*</span><span class="p">)</span><span class="n">buf</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">ndim</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">pointer</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">strides</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">indices</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">suboffsets</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">&gt;=</span><span class="mi">0</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">pointer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">*</span><span class="p">((</span><span class="kt">char</span><span class="o">**</span><span class="p">)</span><span class="n">pointer</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">suboffsets</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="kt">void</span><span class="o">*</span><span class="p">)</span><span class="n">pointer</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
</section>
<section id="buffer-related-functions">
<h2>缓冲区相关函数<a class="headerlink" href="#buffer-related-functions" title="永久链接至标题"></a></h2>
<dl class="function">
<dt id="c.PyObject_CheckBuffer">
int <code class="sig-name descname">PyObject_CheckBuffer</code><span class="sig-paren">(</span><a class="reference internal" href="structures.html#c.PyObject" title="PyObject">PyObject</a><em> *obj</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyObject_CheckBuffer" title="永久链接至目标"></a></dt>
<dd><p>如果 <em>obj</em> 支持缓冲区接口,则返回 <code class="docutils literal notranslate"><span class="pre">1</span></code>,否则返回 <code class="docutils literal notranslate"><span class="pre">0</span></code>。 返回 <code class="docutils literal notranslate"><span class="pre">1</span></code> 时不保证 <a class="reference internal" href="#c.PyObject_GetBuffer" title="PyObject_GetBuffer"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_GetBuffer()</span></code></a> 一定成功。本函数一定调用成功。</p>
</dd></dl>
<dl class="function">
<dt id="c.PyObject_GetBuffer">
int <code class="sig-name descname">PyObject_GetBuffer</code><span class="sig-paren">(</span><a class="reference internal" href="structures.html#c.PyObject" title="PyObject">PyObject</a><em> *exporter</em>, <a class="reference internal" href="#c.Py_buffer" title="Py_buffer">Py_buffer</a><em> *view</em>, int<em> flags</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyObject_GetBuffer" title="永久链接至目标"></a></dt>
<dd><p><em>输出器程序</em> 发送请求,按照 <em>flags</em> 指定的内容填充 <em>view</em>。如果 输出器程序不能提供准确类型的缓冲区,<em>必须</em> 触发 <code class="xref c c-data docutils literal notranslate"><span class="pre">PyExc_BufferError</span></code>,设置 <code class="docutils literal notranslate"><span class="pre">view-&gt;obj</span></code><code class="docutils literal notranslate"><span class="pre">NULL</span></code> 并返回 <code class="docutils literal notranslate"><span class="pre">-1</span></code></p>
<p>成功时,填充 <em>view</em>,将 <code class="docutils literal notranslate"><span class="pre">view-&gt;obj</span></code> 设为对 <em>exporter</em> 的新引用,并返回 0。 当链式缓冲区提供程序将请求重定向到一个对象时,<code class="docutils literal notranslate"><span class="pre">view-&gt;obj</span></code> 可以引用该对象而不是 <em>exporter</em> (参见 <a class="reference internal" href="typeobj.html#buffer-structs"><span class="std std-ref">缓冲区对象结构</span></a>)。</p>
<p><a class="reference internal" href="#c.PyObject_GetBuffer" title="PyObject_GetBuffer"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_GetBuffer()</span></code></a> 必须与 <a class="reference internal" href="#c.PyBuffer_Release" title="PyBuffer_Release"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyBuffer_Release()</span></code></a> 同时调用成功,类似于 <code class="xref c c-func docutils literal notranslate"><span class="pre">malloc()</span></code><code class="xref c c-func docutils literal notranslate"><span class="pre">free()</span></code>。因此,消费者程序用完缓冲区后, <a class="reference internal" href="#c.PyBuffer_Release" title="PyBuffer_Release"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyBuffer_Release()</span></code></a> 必须保证被调用一次。</p>
</dd></dl>
<dl class="function">
<dt id="c.PyBuffer_Release">
void <code class="sig-name descname">PyBuffer_Release</code><span class="sig-paren">(</span><a class="reference internal" href="#c.Py_buffer" title="Py_buffer">Py_buffer</a><em> *view</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyBuffer_Release" title="永久链接至目标"></a></dt>
<dd><p>释放缓冲区 <em>view</em> 并递减 <code class="docutils literal notranslate"><span class="pre">view-&gt;obj</span></code> 的引用计数。该函数必须在缓冲区不再使用时才能调用,否则可能会发生引用泄漏。</p>
<p>若该函数针对的缓冲区不是通过 <a class="reference internal" href="#c.PyObject_GetBuffer" title="PyObject_GetBuffer"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_GetBuffer()</span></code></a> 获得的,将会出错。</p>
</dd></dl>
<dl class="function">
<dt id="c.PyBuffer_SizeFromFormat">
Py_ssize_t <code class="sig-name descname">PyBuffer_SizeFromFormat</code><span class="sig-paren">(</span>const char<em> *</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyBuffer_SizeFromFormat" title="永久链接至目标"></a></dt>
<dd><p>Return the implied <a class="reference internal" href="#c.Py_buffer.itemsize" title="Py_buffer.itemsize"><code class="xref c c-data docutils literal notranslate"><span class="pre">itemsize</span></code></a> from <a class="reference internal" href="#c.Py_buffer.format" title="Py_buffer.format"><code class="xref c c-data docutils literal notranslate"><span class="pre">format</span></code></a>.
This function is not yet implemented.</p>
</dd></dl>
<dl class="function">
<dt id="c.PyBuffer_IsContiguous">
int <code class="sig-name descname">PyBuffer_IsContiguous</code><span class="sig-paren">(</span><a class="reference internal" href="#c.Py_buffer" title="Py_buffer">Py_buffer</a><em> *view</em>, char<em> order</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyBuffer_IsContiguous" title="永久链接至目标"></a></dt>
<dd><p>如果 <em>view</em> 定义的内存是 C 风格(<em>order</em><code class="docutils literal notranslate"><span class="pre">'C'</span></code>)或 Fortran 风格(<em>order</em><code class="docutils literal notranslate"><span class="pre">'F'</span></code> <a class="reference internal" href="../glossary.html#term-contiguous"><span class="xref std std-term">contiguous</span></a> 或其中之一(<em>order</em><code class="docutils literal notranslate"><span class="pre">'A'</span></code>),则返回 <code class="docutils literal notranslate"><span class="pre">1</span></code>。否则返回 <code class="docutils literal notranslate"><span class="pre">0</span></code>。该函数总会成功。</p>
</dd></dl>
<dl class="function">
<dt id="c.PyBuffer_GetPointer">
void* <code class="sig-name descname">PyBuffer_GetPointer</code><span class="sig-paren">(</span><a class="reference internal" href="#c.Py_buffer" title="Py_buffer">Py_buffer</a><em> *view</em>, Py_ssize_t<em> *indices</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyBuffer_GetPointer" title="永久链接至目标"></a></dt>
<dd><p>获取给定 <em>view</em> 内的 <em>indices</em> 所指向的内存区域。<em>indices</em> 必须指向一个 <code class="docutils literal notranslate"><span class="pre">view-&gt;ndim</span></code> 索引的数组。</p>
</dd></dl>
<dl class="function">
<dt id="c.PyBuffer_FromContiguous">
int <code class="sig-name descname">PyBuffer_FromContiguous</code><span class="sig-paren">(</span><a class="reference internal" href="#c.Py_buffer" title="Py_buffer">Py_buffer</a><em> *view</em>, void<em> *buf</em>, Py_ssize_t<em> len</em>, char<em> fort</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyBuffer_FromContiguous" title="永久链接至目标"></a></dt>
<dd><p><em>buf</em> 复制连续的 <em>len</em> 字节到 <em>view</em><em>fort</em> 可以是 <code class="docutils literal notranslate"><span class="pre">'C'</span></code><code class="docutils literal notranslate"><span class="pre">'F'</span></code> (对应于 C 风格或 Fortran 风格的顺序)。成功时返回 <code class="docutils literal notranslate"><span class="pre">0</span></code> ,错误时返回 <code class="docutils literal notranslate"><span class="pre">-1</span></code></p>
</dd></dl>
<dl class="function">
<dt id="c.PyBuffer_ToContiguous">
int <code class="sig-name descname">PyBuffer_ToContiguous</code><span class="sig-paren">(</span>void<em> *buf</em>, <a class="reference internal" href="#c.Py_buffer" title="Py_buffer">Py_buffer</a><em> *src</em>, Py_ssize_t<em> len</em>, char<em> order</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyBuffer_ToContiguous" title="永久链接至目标"></a></dt>
<dd><p><em>src</em> 复制 <em>len</em> 字节到 <em>buf</em> ,成为连续字节串的形式。<em>order</em> 可以是 <code class="docutils literal notranslate"><span class="pre">'C'</span></code><code class="docutils literal notranslate"><span class="pre">'F'</span></code><code class="docutils literal notranslate"><span class="pre">'A'</span></code> (对应于 C 风格、Fortran 风格的顺序或其中任意一种)。成功时返回 <code class="docutils literal notranslate"><span class="pre">0</span></code> ,出错时返回 <code class="docutils literal notranslate"><span class="pre">-1</span></code></p>
<p>如果 <em>len</em> != <em>src-&gt;len</em> 则此函数将报错。</p>
</dd></dl>
<dl class="function">
<dt id="c.PyBuffer_FillContiguousStrides">
void <code class="sig-name descname">PyBuffer_FillContiguousStrides</code><span class="sig-paren">(</span>int<em> ndims</em>, Py_ssize_t<em> *shape</em>, Py_ssize_t<em> *strides</em>, int<em> itemsize</em>, char<em> order</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyBuffer_FillContiguousStrides" title="永久链接至目标"></a></dt>
<dd><p>用给定形状的 <a class="reference internal" href="../glossary.html#term-contiguous"><span class="xref std std-term">contiguous</span></a> 字节串数组 (如果 <em>order</em><code class="docutils literal notranslate"><span class="pre">'C'</span></code> 则为 C 风格,如果 <em>order</em><code class="docutils literal notranslate"><span class="pre">'F'</span></code> 则为 Fortran 风格) 来填充 <em>strides</em> 数组,每个元素具有给定的字节数。</p>
</dd></dl>
<dl class="function">
<dt id="c.PyBuffer_FillInfo">
int <code class="sig-name descname">PyBuffer_FillInfo</code><span class="sig-paren">(</span><a class="reference internal" href="#c.Py_buffer" title="Py_buffer">Py_buffer</a><em> *view</em>, <a class="reference internal" href="structures.html#c.PyObject" title="PyObject">PyObject</a><em> *exporter</em>, void<em> *buf</em>, Py_ssize_t<em> len</em>, int<em> readonly</em>, int<em> flags</em><span class="sig-paren">)</span><a class="headerlink" href="#c.PyBuffer_FillInfo" title="永久链接至目标"></a></dt>
<dd><p>处理导出程序的缓冲区请求,该导出程序要公开大小为 <em>len</em><em>buf</em> ,并根据 <em>readonly</em> 设置可写性。<em>bug</em> 被解释为一个无符号字节序列。</p>
<p>参数 <em>flags</em> 表示请求的类型。该函数总是按照 flag 指定的内容填入 <em>view</em>,除非 <em>buf</em> 设为只读,并且 <em>flag</em> 中设置了 <a class="reference internal" href="#c.PyBUF_WRITABLE" title="PyBUF_WRITABLE"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyBUF_WRITABLE</span></code></a> 标志。</p>
<p>成功时,将 <code class="docutils literal notranslate"><span class="pre">view-&gt;obj</span></code> 设为 <em>exporter</em> 的新引用,并返回 0。否则引发 <code class="xref c c-data docutils literal notranslate"><span class="pre">PyExc_BufferError</span></code> ,将 <code class="docutils literal notranslate"><span class="pre">view-&gt;obj</span></code> 设为 <code class="docutils literal notranslate"><span class="pre">NULL</span></code>,并返回 <code class="docutils literal notranslate"><span class="pre">-1</span></code></p>
<p>如果此函数用作 <a class="reference internal" href="typeobj.html#buffer-structs"><span class="std std-ref">getbufferproc</span></a> 的一部分,则 <em>exporter</em> 必须设置为导出对象,并且必须在未修改的情况下传递 <em>flags</em>。否则,<em>exporter</em> 必须是 <code class="docutils literal notranslate"><span class="pre">NULL</span></code></p>
</dd></dl>
</section>
</section>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h3><a href="../contents.html">目录</a></h3>
<ul>
<li><a class="reference internal" href="#">缓冲协议</a><ul>
<li><a class="reference internal" href="#buffer-structure">缓冲区结构</a></li>
<li><a class="reference internal" href="#buffer-request-types">缓冲区请求的类型</a><ul>
<li><a class="reference internal" href="#request-independent-fields">与请求无关的字段</a></li>
<li><a class="reference internal" href="#readonly-format">只读,格式</a></li>
<li><a class="reference internal" href="#shape-strides-suboffsets">形状,步幅,子偏移量</a></li>
<li><a class="reference internal" href="#contiguity-requests">连续性的请求</a></li>
<li><a class="reference internal" href="#compound-requests">复合请求</a></li>
</ul>
</li>
<li><a class="reference internal" href="#complex-arrays">复杂数组</a><ul>
<li><a class="reference internal" href="#numpy-style-shape-and-strides">NumPy-风格:形状和步幅</a></li>
<li><a class="reference internal" href="#pil-style-shape-strides-and-suboffsets">PIL-风格:形状,步幅和子偏移量</a></li>
</ul>
</li>
<li><a class="reference internal" href="#buffer-related-functions">缓冲区相关函数</a></li>
</ul>
</li>
</ul>
<h4>上一个主题</h4>
<p class="topless"><a href="iter.html"
title="上一章">迭代器协议</a></p>
<h4>下一个主题</h4>
<p class="topless"><a href="objbuffer.html"
title="下一章">旧缓冲协议</a></p>
<div role="note" aria-label="source link">
<h3>本页</h3>
<ul class="this-page-menu">
<li><a href="../bugs.html">报告 Bug</a></li>
<li>
<a href="https://github.com/python/cpython/blob/3.8/Doc/c-api/buffer.rst"
rel="nofollow">显示源代码
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>导航</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="总目录"
>索引</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python 模块索引"
>模块</a> |</li>
<li class="right" >
<a href="objbuffer.html" title="旧缓冲协议"
>下一页</a> |</li>
<li class="right" >
<a href="iter.html" title="迭代器协议"
>上一页</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.8.20 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python/C API 参考手册</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="abstract.html" >抽象对象层</a> &#187;</li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
<input type="submit" value="转向" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
|
</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">版权所有</a> 2001-2024, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
<br />
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
<br />
最后更新于 12月 09, 2024.
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 2.4.4.
</div>
</body>
</html>