mirror of
https://github.com/fofolee/uTools-Manuals.git
synced 2025-06-08 23:14:06 +08:00
578 lines
247 KiB
HTML
578 lines
247 KiB
HTML
<div class="body" role="main"><div class="section" id="module-ctypes"><h1><span class="yiyi-st" id="yiyi-10">16.16. <a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a> - Python的外部函数库</span></h1><p><span class="yiyi-st" id="yiyi-11"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>是Python的外部函数库。</span><span class="yiyi-st" id="yiyi-12">它提供C兼容的数据类型,并允许调用DLL或共享库中的函数。</span><span class="yiyi-st" id="yiyi-13">它可以用来将这些库封装在纯Python中。</span></p><div class="section" id="ctypes-tutorial"><h2><span class="yiyi-st" id="yiyi-14">16.16.1. ctypes 教程 </span></h2><p><span class="yiyi-st" id="yiyi-15">注意:本教程中的代码示例使用<a class="reference internal" href="doctest.html#module-doctest" title="doctest: Test pieces of code within docstrings."><code class="xref py py-mod docutils literal"><span class="pre">doctest</span></code></a>确保它们实际工作。</span><span class="yiyi-st" id="yiyi-16">由于一些代码示例在Linux,Windows或Mac OS X下表现不同,因此它们在注释中包含doctest指令。</span></p><p><span class="yiyi-st" id="yiyi-17">注意:一些代码示例引用了ctypes <a class="reference internal" href="#ctypes.c_int" title="ctypes.c_int"><code class="xref py py-class docutils literal"><span class="pre">c_int</span></code></a>类型。</span><span class="yiyi-st" id="yiyi-18">在<code class="docutils literal"><span class="pre">sizeof(long)</span> <span class="pre">==</span> <span class="pre">sizeof(int)</span></code>的平台上,它是<a class="reference internal" href="#ctypes.c_long" title="ctypes.c_long"><code class="xref py py-class docutils literal"><span class="pre">c_long</span></code></a></span><span class="yiyi-st" id="yiyi-19">所以,如果您期望<a class="reference internal" href="#ctypes.c_int" title="ctypes.c_int"><code class="xref py py-class docutils literal"><span class="pre">c_int</span></code></a>打印<a class="reference internal" href="#ctypes.c_long" title="ctypes.c_long"><code class="xref py py-class docutils literal"><span class="pre">c_long</span></code></a> - 它们实际上是相同的类型,您不应该感到困惑。</span></p><div class="section" id="loading-dynamic-link-libraries"><h3><span class="yiyi-st" id="yiyi-20">16.16.1.1. </span><span class="yiyi-st" id="yiyi-21">加载动态链接库</span></h3><p><span class="yiyi-st" id="yiyi-22"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>导出<em>cdll对象,</em>在Windows上导出<em>windll</em>和<em>oledll</em>对象,用于加载动态链接库。</span></p><p><span class="yiyi-st" id="yiyi-23">加载的库作为这些(上述)对象的属性被访问。</span><span class="yiyi-st" id="yiyi-24"><em>cdll</em>加载使用标准<code class="docutils literal"><span class="pre">cdecl</span></code>调用约定导出函数的库,而<em>windll</em>库使用<code class="docutils literal"><span class="pre">stdcall</span></code>调用函数惯例。</span><span class="yiyi-st" id="yiyi-25"><em>oledll</em>也使用<code class="docutils literal"><span class="pre">stdcall</span></code>调用约定,并假定函数返回一个Windows <code class="xref c c-type docutils literal"><span class="pre">HRESULT</span></code>错误代码。</span><span class="yiyi-st" id="yiyi-26">错误代码用于在函数调用失败时自动引发<a class="reference internal" href="exceptions.html#OSError" title="OSError"><code class="xref py py-class docutils literal"><span class="pre">OSError</span></code></a>异常。</span></p><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-27"><span class="versionmodified">在版本3.3中已更改:</span>之前Windows的错误通过<a class="reference internal" href="exceptions.html#WindowsError" title="WindowsError"><code class="xref py py-exc docutils literal"><span class="pre">WindowsError</span></code></a>引发,现在是<a class="reference internal" href="exceptions.html#OSError" title="OSError"><code class="xref py py-exc docutils literal"><span class="pre">OSError</span></code></a>的别名。</span></p></div><p><span class="yiyi-st" id="yiyi-28">以下是Windows的一些示例。</span><span class="yiyi-st" id="yiyi-29">请注意,<code class="docutils literal"><span class="pre">msvcrt</span></code>是包含大多数标准C函数的MS标准C库,并使用cdecl调用约定:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes</span> <span class="k">import</span> <span class="o">*</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">windll</span><span class="o">.</span><span class="n">kernel32</span><span class="p">)</span>
|
||
<span class="go"><WinDLL 'kernel32', handle ... at ...></span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">cdll</span><span class="o">.</span><span class="n">msvcrt</span><span class="p">)</span>
|
||
<span class="go"><CDLL 'msvcrt', handle ... at ...></span>
|
||
<span class="gp">>>> </span><span class="n">libc</span> <span class="o">=</span> <span class="n">cdll</span><span class="o">.</span><span class="n">msvcrt</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-30">Windows会自动附加通常的<code class="docutils literal"><span class="pre">.dll</span></code>文件后缀。</span></p><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-31">注意</span></p><p class="last"><span class="yiyi-st" id="yiyi-32">通过<code class="docutils literal"><span class="pre">cdll.msvcrt</span></code>访问标准C库将使用该库的过时版本,该版本可能与Python正在使用的版本不兼容。</span><span class="yiyi-st" id="yiyi-33">在可能的情况下,使用本地Python功能,或者导入并使用<code class="docutils literal"><span class="pre">msvcrt</span></code>模块。</span></p></div><p><span class="yiyi-st" id="yiyi-34">在Linux上,需要指定文件名<em>(包括扩展名)</em>以加载库,因此属性访问不能用于加载库。</span><span class="yiyi-st" id="yiyi-35">可以使用dll加载器的<code class="xref py py-meth docutils literal"><span class="pre">LoadLibrary()</span></code>方法,或者通过调用构造函数创建CDLL的实例来加载库:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">cdll</span><span class="o">.</span><span class="n">LoadLibrary</span><span class="p">(</span><span class="s2">"libc.so.6"</span><span class="p">)</span>
|
||
<span class="go"><CDLL 'libc.so.6', handle ... at ...></span>
|
||
<span class="gp">>>> </span><span class="n">libc</span> <span class="o">=</span> <span class="n">CDLL</span><span class="p">(</span><span class="s2">"libc.so.6"</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">libc</span>
|
||
<span class="go"><CDLL 'libc.so.6', handle ... at ...></span>
|
||
<span class="go">>>></span>
|
||
</code></pre></div><div class="section" id="accessing-functions-from-loaded-dlls"><h3><span class="yiyi-st" id="yiyi-36">16.16.1.2. </span><span class="yiyi-st" id="yiyi-37">从加载的dll中访问函数</span></h3><p><span class="yiyi-st" id="yiyi-38">函数作为dll对象的属性被访问:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes</span> <span class="k">import</span> <span class="o">*</span>
|
||
<span class="gp">>>> </span><span class="n">libc</span><span class="o">.</span><span class="n">printf</span>
|
||
<span class="go"><_FuncPtr object at 0x...></span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">windll</span><span class="o">.</span><span class="n">kernel32</span><span class="o">.</span><span class="n">GetModuleHandleA</span><span class="p">)</span>
|
||
<span class="go"><_FuncPtr object at 0x...></span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">windll</span><span class="o">.</span><span class="n">kernel32</span><span class="o">.</span><span class="n">MyOwnFunction</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
File <span class="nb">"ctypes.py"</span>, line <span class="m">239</span>, in <span class="n">__getattr__</span>
|
||
<span class="n">func</span> <span class="o">=</span> <span class="n">_StdcallFuncPtr</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
|
||
<span class="gr">AttributeError</span>: <span class="n">function 'MyOwnFunction' not found</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-39">请注意,像<code class="docutils literal"><span class="pre">kernel32</span></code>和<code class="docutils literal"><span class="pre">user32</span></code>这样的win32系统DLL通常会导出ANSI以及UNICODE版本的函数。</span><span class="yiyi-st" id="yiyi-40">UNICODE版本的名称附加了<code class="docutils literal"><span class="pre">W</span></code>,而ANSI版本的名称附有<code class="docutils literal"><span class="pre">A</span></code>。</span><span class="yiyi-st" id="yiyi-41">为给定模块名称返回一个<em>模块句柄</em>的win32 <code class="docutils literal"><span class="pre">GetModuleHandle</span></code>函数具有以下C原型,并且使用一个宏将其中一个暴露为<code class="docutils literal"><span class="pre">GetModuleHandle</span></code>取决于是否定义了UNICODE:</span></p><pre><code class="language-python"><span></span><span class="o">/*</span> <span class="n">ANSI</span> <span class="n">version</span> <span class="o">*/</span>
|
||
<span class="n">HMODULE</span> <span class="n">GetModuleHandleA</span><span class="p">(</span><span class="n">LPCSTR</span> <span class="n">lpModuleName</span><span class="p">);</span>
|
||
<span class="o">/*</span> <span class="n">UNICODE</span> <span class="n">version</span> <span class="o">*/</span>
|
||
<span class="n">HMODULE</span> <span class="n">GetModuleHandleW</span><span class="p">(</span><span class="n">LPCWSTR</span> <span class="n">lpModuleName</span><span class="p">);</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-42"><em>windll</em>不会尝试通过magic选择其中的一个,您必须明确指定<code class="docutils literal"><span class="pre">GetModuleHandleA</span></code>或<code class="docutils literal"><span class="pre">GetModuleHandleW</span></code>来访问所需的版本,然后调用它分别与字节或字符串对象。</span></p><p><span class="yiyi-st" id="yiyi-43">有时候,dll会导出名称不是有效Python标识符的函数,如<code class="docutils literal"><span class="pre">"??2@YAPAXI@Z"</span></code>。</span><span class="yiyi-st" id="yiyi-44">在这种情况下,您必须使用<a class="reference internal" href="functions.html#getattr" title="getattr"><code class="xref py py-func docutils literal"><span class="pre">getattr()</span></code></a>来检索函数:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="nb">getattr</span><span class="p">(</span><span class="n">cdll</span><span class="o">.</span><span class="n">msvcrt</span><span class="p">,</span> <span class="s2">"??2@YAPAXI@Z"</span><span class="p">)</span>
|
||
<span class="go"><_FuncPtr object at 0x...></span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-45">在Windows上,一些dll导出函数不是按名称,而是按序号。</span><span class="yiyi-st" id="yiyi-46">这些函数可以通过使用序号索引dll对象来访问:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">cdll</span><span class="o">.</span><span class="n">kernel32</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||
<span class="go"><_FuncPtr object at 0x...></span>
|
||
<span class="gp">>>> </span><span class="n">cdll</span><span class="o">.</span><span class="n">kernel32</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
File <span class="nb">"ctypes.py"</span>, line <span class="m">310</span>, in <span class="n">__getitem__</span>
|
||
<span class="n">func</span> <span class="o">=</span> <span class="n">_StdcallFuncPtr</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
|
||
<span class="gr">AttributeError</span>: <span class="n">function ordinal 0 not found</span>
|
||
<span class="go">>>></span>
|
||
</code></pre></div><div class="section" id="calling-functions"><h3><span class="yiyi-st" id="yiyi-47">16.16.1.3. </span><span class="yiyi-st" id="yiyi-48">调用函数</span></h3><p><span class="yiyi-st" id="yiyi-49">你可以像任何其他Python可调用一样调用这些函数。</span><span class="yiyi-st" id="yiyi-50">这个例子使用<code class="docutils literal"><span class="pre">time()</span></code>函数,它返回自Unix纪元以来的系统时间(秒)和<code class="docutils literal"><span class="pre">GetModuleHandleA()</span></code>函数,它返回一个win32模块句柄。</span></p><p><span class="yiyi-st" id="yiyi-51">这个例子用NULL指针调用两个函数(<code class="docutils literal"><span class="pre">None</span></code>应该用作NULL指针):</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">libc</span><span class="o">.</span><span class="n">time</span><span class="p">(</span><span class="kc">None</span><span class="p">))</span>
|
||
<span class="go">1150640792</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="nb">hex</span><span class="p">(</span><span class="n">windll</span><span class="o">.</span><span class="n">kernel32</span><span class="o">.</span><span class="n">GetModuleHandleA</span><span class="p">(</span><span class="kc">None</span><span class="p">)))</span>
|
||
<span class="go">0x1d000000</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-52"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>试图保护你免于调用具有错误数量的参数或错误的调用约定的函数。</span><span class="yiyi-st" id="yiyi-53">不幸的是,这只适用于Windows。</span><span class="yiyi-st" id="yiyi-54">它通过在函数返回后检查堆栈来实现,因此尽管出现错误,但函数<em>已被调用:</em></span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">windll</span><span class="o">.</span><span class="n">kernel32</span><span class="o">.</span><span class="n">GetModuleHandleA</span><span class="p">()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
<span class="gr">ValueError</span>: <span class="n">Procedure probably called with not enough arguments (4 bytes missing)</span>
|
||
<span class="gp">>>> </span><span class="n">windll</span><span class="o">.</span><span class="n">kernel32</span><span class="o">.</span><span class="n">GetModuleHandleA</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
<span class="gr">ValueError</span>: <span class="n">Procedure probably called with too many arguments (4 bytes in excess)</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-55">使用<code class="docutils literal"><span class="pre">cdecl</span></code>调用约定调用<code class="docutils literal"><span class="pre">stdcall</span></code>函数时会引发相同的异常,反之亦然:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">cdll</span><span class="o">.</span><span class="n">kernel32</span><span class="o">.</span><span class="n">GetModuleHandleA</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
<span class="gr">ValueError</span>: <span class="n">Procedure probably called with not enough arguments (4 bytes missing)</span>
|
||
<span class="go">>>></span>
|
||
|
||
<span class="gp">>>> </span><span class="n">windll</span><span class="o">.</span><span class="n">msvcrt</span><span class="o">.</span><span class="n">printf</span><span class="p">(</span><span class="n">b</span><span class="s2">"spam"</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
<span class="gr">ValueError</span>: <span class="n">Procedure probably called with too many arguments (4 bytes in excess)</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-56">要找出正确的调用约定,必须查看C头文件或要调用的函数的文档。</span></p><p><span class="yiyi-st" id="yiyi-57">在Windows上,<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>使用win32结构化异常处理来防止在使用无效参数值调用函数时出现通用保护错误的崩溃:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">windll</span><span class="o">.</span><span class="n">kernel32</span><span class="o">.</span><span class="n">GetModuleHandleA</span><span class="p">(</span><span class="mi">32</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
<span class="gr">OSError</span>: <span class="n">exception: access violation reading 0x00000020</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-58">然而,有足够的方法使Python与<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>崩溃,所以你应该小心。</span><span class="yiyi-st" id="yiyi-59"><a class="reference internal" href="faulthandler.html#module-faulthandler" title="faulthandler: Dump the Python traceback."><code class="xref py py-mod docutils literal"><span class="pre">faulthandler</span></code></a>模块可以帮助您调试崩溃(例如,</span><span class="yiyi-st" id="yiyi-60">来自错误的C库调用产生的分割错误)。</span></p><p><span class="yiyi-st" id="yiyi-61"><code class="docutils literal"><span class="pre">None</span></code>, integers, bytes objects and (unicode) strings are the only native Python objects that can directly be used as parameters in these function calls. </span><span class="yiyi-st" id="yiyi-62"><code class="docutils literal"><span class="pre">None</span></code> is passed as a C <code class="docutils literal"><span class="pre">NULL</span></code> pointer, bytes objects and strings are passed as pointer to the memory block that contains their data (<code class="xref c c-type docutils literal"><span class="pre">char</span> <span class="pre">*</span></code> or <code class="xref c c-type docutils literal"><span class="pre">wchar_t</span> <span class="pre">*</span></code>). </span><span class="yiyi-st" id="yiyi-63">Python整数作为平台默认的C <code class="xref c c-type docutils literal"><span class="pre">int</span></code>类型传递,它们的值被屏蔽以适合C类型。</span></p><p><span class="yiyi-st" id="yiyi-64">在继续使用其他参数类型调用函数之前,我们必须了解更多关于<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>数据类型。</span></p></div><div class="section" id="fundamental-data-types"><h3><span class="yiyi-st" id="yiyi-65">16.16.1.4. </span><span class="yiyi-st" id="yiyi-66">基本数据类型</span></h3><p><span class="yiyi-st" id="yiyi-67"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>定义了许多基本的C兼容数据类型:</span></p><table border="1" class="docutils"><thead valign="bottom"><tr class="row-odd"><th class="head"><span class="yiyi-st" id="yiyi-68">ctypes类型</span></th><th class="head"><span class="yiyi-st" id="yiyi-69">C类型</span></th><th class="head"><span class="yiyi-st" id="yiyi-70">Python类型</span></th></tr></thead><tbody valign="top"><tr class="row-even"><td><span class="yiyi-st" id="yiyi-71"><a class="reference internal" href="#ctypes.c_bool" title="ctypes.c_bool"><code class="xref py py-class docutils literal"><span class="pre">c_bool</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-72"><code class="xref c c-type docutils literal"><span class="pre">_Bool</span></code></span></td><td><span class="yiyi-st" id="yiyi-73">布尔(1)</span></td></tr><tr class="row-odd"><td><span class="yiyi-st" id="yiyi-74"><a class="reference internal" href="#ctypes.c_char" title="ctypes.c_char"><code class="xref py py-class docutils literal"><span class="pre">c_char</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-75"><code class="xref c c-type docutils literal"><span class="pre">char</span></code></span></td><td><span class="yiyi-st" id="yiyi-76">1个字符的字节对象</span></td></tr><tr class="row-even"><td><span class="yiyi-st" id="yiyi-77"><a class="reference internal" href="#ctypes.c_wchar" title="ctypes.c_wchar"><code class="xref py py-class docutils literal"><span class="pre">c_wchar</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-78"><code class="xref c c-type docutils literal"><span class="pre">wchar_t</span></code></span></td><td><span class="yiyi-st" id="yiyi-79">1个字符的字符串</span></td></tr><tr class="row-odd"><td><span class="yiyi-st" id="yiyi-80"><a class="reference internal" href="#ctypes.c_byte" title="ctypes.c_byte"><code class="xref py py-class docutils literal"><span class="pre">c_byte</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-81"><code class="xref c c-type docutils literal"><span class="pre">char</span></code></span></td><td><span class="yiyi-st" id="yiyi-82">INT</span></td></tr><tr class="row-even"><td><span class="yiyi-st" id="yiyi-83"><a class="reference internal" href="#ctypes.c_ubyte" title="ctypes.c_ubyte"><code class="xref py py-class docutils literal"><span class="pre">c_ubyte</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-84"><code class="xref c c-type docutils literal"><span class="pre">unsigned</span> <span class="pre">char</span></code></span></td><td><span class="yiyi-st" id="yiyi-85">INT</span></td></tr><tr class="row-odd"><td><span class="yiyi-st" id="yiyi-86"><a class="reference internal" href="#ctypes.c_short" title="ctypes.c_short"><code class="xref py py-class docutils literal"><span class="pre">c_short</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-87"><code class="xref c c-type docutils literal"><span class="pre">short</span></code></span></td><td><span class="yiyi-st" id="yiyi-88">INT</span></td></tr><tr class="row-even"><td><span class="yiyi-st" id="yiyi-89"><a class="reference internal" href="#ctypes.c_ushort" title="ctypes.c_ushort"><code class="xref py py-class docutils literal"><span class="pre">c_ushort</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-90"><code class="xref c c-type docutils literal"><span class="pre">unsigned</span> <span class="pre">short</span></code></span></td><td><span class="yiyi-st" id="yiyi-91">INT</span></td></tr><tr class="row-odd"><td><span class="yiyi-st" id="yiyi-92"><a class="reference internal" href="#ctypes.c_int" title="ctypes.c_int"><code class="xref py py-class docutils literal"><span class="pre">c_int</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-93"><code class="xref c c-type docutils literal"><span class="pre">int</span></code></span></td><td><span class="yiyi-st" id="yiyi-94">INT</span></td></tr><tr class="row-even"><td><span class="yiyi-st" id="yiyi-95"><a class="reference internal" href="#ctypes.c_uint" title="ctypes.c_uint"><code class="xref py py-class docutils literal"><span class="pre">c_uint</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-96"><code class="xref c c-type docutils literal"><span class="pre">unsigned</span> <span class="pre">int</span></code></span></td><td><span class="yiyi-st" id="yiyi-97">INT</span></td></tr><tr class="row-odd"><td><span class="yiyi-st" id="yiyi-98"><a class="reference internal" href="#ctypes.c_long" title="ctypes.c_long"><code class="xref py py-class docutils literal"><span class="pre">c_long</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-99"><code class="xref c c-type docutils literal"><span class="pre">long</span></code></span></td><td><span class="yiyi-st" id="yiyi-100">INT</span></td></tr><tr class="row-even"><td><span class="yiyi-st" id="yiyi-101"><a class="reference internal" href="#ctypes.c_ulong" title="ctypes.c_ulong"><code class="xref py py-class docutils literal"><span class="pre">c_ulong</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-102"><code class="xref c c-type docutils literal"><span class="pre">unsigned</span> <span class="pre">long</span></code></span></td><td><span class="yiyi-st" id="yiyi-103">INT</span></td></tr><tr class="row-odd"><td><span class="yiyi-st" id="yiyi-104"><a class="reference internal" href="#ctypes.c_longlong" title="ctypes.c_longlong"><code class="xref py py-class docutils literal"><span class="pre">c_longlong</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-105"><code class="xref c c-type docutils literal"><span class="pre">__int64</span></code>或<code class="xref c c-type docutils literal"><span class="pre">长</span> <span class="pre">长</span></code></span></td><td><span class="yiyi-st" id="yiyi-106">INT</span></td></tr><tr class="row-even"><td><span class="yiyi-st" id="yiyi-107"><a class="reference internal" href="#ctypes.c_ulonglong" title="ctypes.c_ulonglong"><code class="xref py py-class docutils literal"><span class="pre">c_ulonglong</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-108"><code class="xref c c-type docutils literal"><span class="pre">无符号</span> <span class="pre">__ int64</span></code>或<code class="xref c c-type docutils literal"><span class="pre">无符号</span> <span class="pre">长</span> <span class="pre">长 t6 > T3></span></code></span></td><td><span class="yiyi-st" id="yiyi-109">INT</span></td></tr><tr class="row-odd"><td><span class="yiyi-st" id="yiyi-110"><a class="reference internal" href="#ctypes.c_size_t" title="ctypes.c_size_t"><code class="xref py py-class docutils literal"><span class="pre">c_size_t</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-111"><code class="xref c c-type docutils literal"><span class="pre">size_t</span></code></span></td><td><span class="yiyi-st" id="yiyi-112">INT</span></td></tr><tr class="row-even"><td><span class="yiyi-st" id="yiyi-113"><a class="reference internal" href="#ctypes.c_ssize_t" title="ctypes.c_ssize_t"><code class="xref py py-class docutils literal"><span class="pre">c_ssize_t</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-114"><code class="xref c c-type docutils literal"><span class="pre">ssize_t</span></code>或<code class="xref c c-type docutils literal"><span class="pre">Py_ssize_t</span></code></span></td><td><span class="yiyi-st" id="yiyi-115">INT</span></td></tr><tr class="row-odd"><td><span class="yiyi-st" id="yiyi-116"><a class="reference internal" href="#ctypes.c_float" title="ctypes.c_float"><code class="xref py py-class docutils literal"><span class="pre">c_float</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-117"><code class="xref c c-type docutils literal"><span class="pre">float</span></code></span></td><td><span class="yiyi-st" id="yiyi-118">浮动</span></td></tr><tr class="row-even"><td><span class="yiyi-st" id="yiyi-119"><a class="reference internal" href="#ctypes.c_double" title="ctypes.c_double"><code class="xref py py-class docutils literal"><span class="pre">c_double</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-120"><code class="xref c c-type docutils literal"><span class="pre">double</span></code></span></td><td><span class="yiyi-st" id="yiyi-121">浮动</span></td></tr><tr class="row-odd"><td><span class="yiyi-st" id="yiyi-122"><a class="reference internal" href="#ctypes.c_longdouble" title="ctypes.c_longdouble"><code class="xref py py-class docutils literal"><span class="pre">c_longdouble</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-123"><code class="xref c c-type docutils literal"><span class="pre">long</span> <span class="pre">double</span></code></span></td><td><span class="yiyi-st" id="yiyi-124">浮动</span></td></tr><tr class="row-even"><td><span class="yiyi-st" id="yiyi-125"><a class="reference internal" href="#ctypes.c_char_p" title="ctypes.c_char_p"><code class="xref py py-class docutils literal"><span class="pre">c_char_p</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-126"><code class="xref c c-type docutils literal"><span class="pre">char</span> <span class="pre">*</span></code>(NUL已终止)</span></td><td><span class="yiyi-st" id="yiyi-127">字节对象或<code class="docutils literal"><span class="pre">None</span></code></span></td></tr><tr class="row-odd"><td><span class="yiyi-st" id="yiyi-128"><a class="reference internal" href="#ctypes.c_wchar_p" title="ctypes.c_wchar_p"><code class="xref py py-class docutils literal"><span class="pre">c_wchar_p</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-129"><code class="xref c c-type docutils literal"><span class="pre">wchar_t</span> <span class="pre">*</span></code>(NUL已终止)</span></td><td><span class="yiyi-st" id="yiyi-130">字符串或<code class="docutils literal"><span class="pre">None</span></code></span></td></tr><tr class="row-even"><td><span class="yiyi-st" id="yiyi-131"><a class="reference internal" href="#ctypes.c_void_p" title="ctypes.c_void_p"><code class="xref py py-class docutils literal"><span class="pre">c_void_p</span></code></a></span></td><td><span class="yiyi-st" id="yiyi-132"><code class="xref c c-type docutils literal"><span class="pre">空</span> <span class="pre">*</span></code></span></td><td><span class="yiyi-st" id="yiyi-133">int或<code class="docutils literal"><span class="pre">None</span></code></span></td></tr></tbody></table><ol class="arabic simple"><li><span class="yiyi-st" id="yiyi-134">构造函数接受任何具有真值的对象。</span></li></ol><p><span class="yiyi-st" id="yiyi-135">所有这些类型都可以通过使用正确类型和值的可选初始值设定项来调用它们来创建:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">c_int</span><span class="p">()</span>
|
||
<span class="go">c_long(0)</span>
|
||
<span class="gp">>>> </span><span class="n">c_wchar_p</span><span class="p">(</span><span class="s2">"Hello, World"</span><span class="p">)</span>
|
||
<span class="go">c_wchar_p('Hello, World')</span>
|
||
<span class="gp">>>> </span><span class="n">c_ushort</span><span class="p">(</span><span class="o">-</span><span class="mi">3</span><span class="p">)</span>
|
||
<span class="go">c_ushort(65533)</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-136">由于这些类型是可变的,它们的值也可以在之后改变:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">i</span> <span class="o">=</span> <span class="n">c_int</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
|
||
<span class="go">c_long(42)</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
||
<span class="go">42</span>
|
||
<span class="gp">>>> </span><span class="n">i</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="o">-</span><span class="mi">99</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
||
<span class="go">-99</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-137">为指针类型<a class="reference internal" href="#ctypes.c_char_p" title="ctypes.c_char_p"><code class="xref py py-class docutils literal"><span class="pre">c_char_p</span></code></a>,<a class="reference internal" href="#ctypes.c_wchar_p" title="ctypes.c_wchar_p"><code class="xref py py-class docutils literal"><span class="pre">c_wchar_p</span></code></a>和<a class="reference internal" href="#ctypes.c_void_p" title="ctypes.c_void_p"><code class="xref py py-class docutils literal"><span class="pre">c_void_p</span></code></a>的实例指定一个新值会改变它们指向的<em>内存位置</em> to,<em>不是内存块的内容(当然不是,因为Python字节对象是不可变的):</em></span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="s2">"Hello, World"</span>
|
||
<span class="gp">>>> </span><span class="n">c_s</span> <span class="o">=</span> <span class="n">c_wchar_p</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">c_s</span><span class="p">)</span>
|
||
<span class="go">c_wchar_p('Hello, World')</span>
|
||
<span class="gp">>>> </span><span class="n">c_s</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="s2">"Hi, there"</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">c_s</span><span class="p">)</span>
|
||
<span class="go">c_wchar_p('Hi, there')</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="c1"># first object is unchanged</span>
|
||
<span class="go">Hello, World</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-138">但是,您应该小心,不要将它们传递给期望指向可变内存的函数。</span><span class="yiyi-st" id="yiyi-139">如果你需要可变内存块,ctypes有一个<a class="reference internal" href="#ctypes.create_string_buffer" title="ctypes.create_string_buffer"><code class="xref py py-func docutils literal"><span class="pre">create_string_buffer()</span></code></a>函数,它以各种方式创建这些函数。</span><span class="yiyi-st" id="yiyi-140">可以使用<code class="docutils literal"><span class="pre">raw</span></code>属性访问(或更改)当前内存块内容;如果您想以NUL结尾的字符串的形式访问它,请使用<code class="docutils literal"><span class="pre">value</span></code>属性:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes</span> <span class="k">import</span> <span class="o">*</span>
|
||
<span class="gp">>>> </span><span class="n">p</span> <span class="o">=</span> <span class="n">create_string_buffer</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span> <span class="c1"># create a 3 byte buffer, initialized to NUL bytes</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="nb">repr</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">raw</span><span class="p">))</span>
|
||
<span class="go">3 b'\x00\x00\x00'</span>
|
||
<span class="gp">>>> </span><span class="n">p</span> <span class="o">=</span> <span class="n">create_string_buffer</span><span class="p">(</span><span class="n">b</span><span class="s2">"Hello"</span><span class="p">)</span> <span class="c1"># create a buffer containing a NUL terminated string</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="nb">repr</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">raw</span><span class="p">))</span>
|
||
<span class="go">6 b'Hello\x00'</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">value</span><span class="p">))</span>
|
||
<span class="go">b'Hello'</span>
|
||
<span class="gp">>>> </span><span class="n">p</span> <span class="o">=</span> <span class="n">create_string_buffer</span><span class="p">(</span><span class="n">b</span><span class="s2">"Hello"</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span> <span class="c1"># create a 10 byte buffer</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="nb">repr</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">raw</span><span class="p">))</span>
|
||
<span class="go">10 b'Hello\x00\x00\x00\x00\x00'</span>
|
||
<span class="gp">>>> </span><span class="n">p</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">b</span><span class="s2">"Hi"</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">),</span> <span class="nb">repr</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">raw</span><span class="p">))</span>
|
||
<span class="go">10 b'Hi\x00lo\x00\x00\x00\x00\x00'</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-141"><a class="reference internal" href="#ctypes.create_string_buffer" title="ctypes.create_string_buffer"><code class="xref py py-func docutils literal"><span class="pre">create_string_buffer()</span></code></a>函数替换了<code class="xref py py-func docutils literal"><span class="pre">c_buffer()</span></code>函数(它仍然可用作别名)以及<code class="xref py py-func docutils literal"><span class="pre">c_string()(它用于早期的ctypes发行版)</span></code>。</span><span class="yiyi-st" id="yiyi-142">要创建包含C类型<code class="xref c c-type docutils literal"><span class="pre">wchar_t</span></code>的unicode字符的可变内存块,请使用<a class="reference internal" href="#ctypes.create_unicode_buffer" title="ctypes.create_unicode_buffer"><code class="xref py py-func docutils literal"><span class="pre">create_unicode_buffer()</span></code></a>函数。</span></p></div><div class="section" id="calling-functions-continued"><h3><span class="yiyi-st" id="yiyi-143">16.16.1.5. </span><span class="yiyi-st" id="yiyi-144">调用函数,继续</span></h3><p><span class="yiyi-st" id="yiyi-145">请注意,printf会打印到真正的标准输出通道<em>而不是</em>到<a class="reference internal" href="sys.html#sys.stdout" title="sys.stdout"><code class="xref py py-data docutils literal"><span class="pre">sys.stdout</span></code></a>,因此这些示例只能在控制台提示符下运行,而不能在<em>IDLE < / t4>或<em>PythonWin</em>:</em></span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">printf</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">printf</span>
|
||
<span class="gp">>>> </span><span class="n">printf</span><span class="p">(</span><span class="n">b</span><span class="s2">"Hello, </span><span class="si">%s</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">b</span><span class="s2">"World!"</span><span class="p">)</span>
|
||
<span class="go">Hello, World!</span>
|
||
<span class="go">14</span>
|
||
<span class="gp">>>> </span><span class="n">printf</span><span class="p">(</span><span class="n">b</span><span class="s2">"Hello, %S</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="s2">"World!"</span><span class="p">)</span>
|
||
<span class="go">Hello, World!</span>
|
||
<span class="go">14</span>
|
||
<span class="gp">>>> </span><span class="n">printf</span><span class="p">(</span><span class="n">b</span><span class="s2">"</span><span class="si">%d</span><span class="s2"> bottles of beer</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="mi">42</span><span class="p">)</span>
|
||
<span class="go">42 bottles of beer</span>
|
||
<span class="go">19</span>
|
||
<span class="gp">>>> </span><span class="n">printf</span><span class="p">(</span><span class="n">b</span><span class="s2">"</span><span class="si">%f</span><span class="s2"> bottles of beer</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="mf">42.5</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
<span class="gr">ArgumentError</span>: <span class="n">argument 2: exceptions.TypeError: Don't know how to convert parameter 2</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-146">如前所述,除整数,字符串和字节对象之外的所有Python类型都必须用相应的<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>类型包装,以便它们可以转换为所需的C数据类型:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">printf</span><span class="p">(</span><span class="n">b</span><span class="s2">"An int </span><span class="si">%d</span><span class="s2">, a double </span><span class="si">%f</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="mi">1234</span><span class="p">,</span> <span class="n">c_double</span><span class="p">(</span><span class="mf">3.14</span><span class="p">))</span>
|
||
<span class="go">An int 1234, a double 3.140000</span>
|
||
<span class="go">31</span>
|
||
<span class="go">>>></span>
|
||
</code></pre></div><div class="section" id="calling-functions-with-your-own-custom-data-types"><h3><span class="yiyi-st" id="yiyi-147">16.16.1.6. </span><span class="yiyi-st" id="yiyi-148">带有自定义类型的函数调用</span></h3><p><span class="yiyi-st" id="yiyi-149">您还可以自定义<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>参数转换,以允许将您自己的类的实例用作函数参数。</span><span class="yiyi-st" id="yiyi-150"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>查找<code class="xref py py-attr docutils literal"><span class="pre">_as_parameter_</span></code>属性并将其用作函数参数。</span><span class="yiyi-st" id="yiyi-151">当然,它必须是整数,字符串或字节之一:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Bottles</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">number</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">_as_parameter_</span> <span class="o">=</span> <span class="n">number</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">bottles</span> <span class="o">=</span> <span class="n">Bottles</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">printf</span><span class="p">(</span><span class="n">b</span><span class="s2">"</span><span class="si">%d</span><span class="s2"> bottles of beer</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">bottles</span><span class="p">)</span>
|
||
<span class="go">42 bottles of beer</span>
|
||
<span class="go">19</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-152">如果您不想将实例的数据存储在<code class="xref py py-attr docutils literal"><span class="pre">_as_parameter_</span></code>实例变量中,则可以定义一个<a class="reference internal" href="functions.html#property" title="property"><code class="xref py py-class docutils literal"><span class="pre">property</span></code></a>,以便根据请求提供该属性。</span></p></div><div class="section" id="specifying-the-required-argument-types-function-prototypes"><h3><span class="yiyi-st" id="yiyi-153">16.16.1.7. </span><span class="yiyi-st" id="yiyi-154">指定必须的参数类型 (函数原型)</span></h3><p><span class="yiyi-st" id="yiyi-155">通过设置<code class="xref py py-attr docutils literal"><span class="pre">argtypes</span></code>属性,可以指定从DLL导出的函数所需的参数类型。</span></p><p><span class="yiyi-st" id="yiyi-156"><code class="xref py py-attr docutils literal"><span class="pre">argtypes</span></code>必须是一个C数据类型的序列(<code class="docutils literal"><span class="pre">printf</span></code>函数在这里可能不是一个好例子,因为它取决于格式的可变数量和不同类型的参数字符串,另一方面,这是非常方便的试验这个功能):</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">printf</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">c_char_p</span><span class="p">,</span> <span class="n">c_char_p</span><span class="p">,</span> <span class="n">c_int</span><span class="p">,</span> <span class="n">c_double</span><span class="p">]</span>
|
||
<span class="gp">>>> </span><span class="n">printf</span><span class="p">(</span><span class="n">b</span><span class="s2">"String '</span><span class="si">%s</span><span class="s2">', Int </span><span class="si">%d</span><span class="s2">, Double </span><span class="si">%f</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">b</span><span class="s2">"Hi"</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mf">2.2</span><span class="p">)</span>
|
||
<span class="go">String 'Hi', Int 10, Double 2.200000</span>
|
||
<span class="go">37</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-157">指定格式可以防止不兼容的参数类型(就像C函数的原型一样),并尝试将参数转换为有效的类型:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">printf</span><span class="p">(</span><span class="n">b</span><span class="s2">"</span><span class="si">%d</span><span class="s2"> </span><span class="si">%d</span><span class="s2"> </span><span class="si">%d</span><span class="s2">"</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
<span class="gr">ArgumentError</span>: <span class="n">argument 2: exceptions.TypeError: wrong type</span>
|
||
<span class="gp">>>> </span><span class="n">printf</span><span class="p">(</span><span class="n">b</span><span class="s2">"</span><span class="si">%s</span><span class="s2"> </span><span class="si">%d</span><span class="s2"> </span><span class="si">%f</span><span class="se">\n</span><span class="s2">"</span><span class="p">,</span> <span class="n">b</span><span class="s2">"X"</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="go">X 2 3.000000</span>
|
||
<span class="go">13</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-158">如果你定义了你自己传递给函数调用的类,你必须实现一个<code class="xref py py-meth docutils literal"><span class="pre">from_param()</span></code>类方法,以使它们能够在<code class="xref py py-attr docutils literal"><span class="pre">argtypes</span></code>序列中使用它们。</span><span class="yiyi-st" id="yiyi-159"><code class="xref py py-meth docutils literal"><span class="pre">from_param()</span></code>类方法接收传递给函数调用的Python对象,它应该执行typecheck或任何需要确保此对象是可被接受的工作,然后返回对象本身,其<code class="xref py py-attr docutils literal"><span class="pre">_as_parameter_</span></code>属性,或者在这种情况下你想要作为C函数参数传递的任何东西。</span><span class="yiyi-st" id="yiyi-160">同样,结果应该是整数,字符串,字节,<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>实例或具有<code class="xref py py-attr docutils literal"><span class="pre">_as_parameter_</span></code>属性的对象。</span></p></div><div class="section" id="return-types"><h3><span class="yiyi-st" id="yiyi-161">16.16.1.8. </span><span class="yiyi-st" id="yiyi-162">返回类型</span></h3><p><span class="yiyi-st" id="yiyi-163">默认情况下,函数被假定为返回C <code class="xref c c-type docutils literal"><span class="pre">int</span></code>类型。</span><span class="yiyi-st" id="yiyi-164">其它返回类型可以通过设置函数对象的<code class="xref py py-attr docutils literal"><span class="pre">restype</span></code>属性来指定。</span></p><p><span class="yiyi-st" id="yiyi-165">这是一个更高级的例子,它使用<code class="docutils literal"><span class="pre">strchr</span></code>函数,它需要一个字符串指针和一个字符,并返回一个指向字符串的指针:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">strchr</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">strchr</span>
|
||
<span class="gp">>>> </span><span class="n">strchr</span><span class="p">(</span><span class="n">b</span><span class="s2">"abcdef"</span><span class="p">,</span> <span class="nb">ord</span><span class="p">(</span><span class="s2">"d"</span><span class="p">))</span>
|
||
<span class="go">8059983</span>
|
||
<span class="gp">>>> </span><span class="n">strchr</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">c_char_p</span> <span class="c1"># c_char_p is a pointer to a string</span>
|
||
<span class="gp">>>> </span><span class="n">strchr</span><span class="p">(</span><span class="n">b</span><span class="s2">"abcdef"</span><span class="p">,</span> <span class="nb">ord</span><span class="p">(</span><span class="s2">"d"</span><span class="p">))</span>
|
||
<span class="go">b'def'</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">strchr</span><span class="p">(</span><span class="n">b</span><span class="s2">"abcdef"</span><span class="p">,</span> <span class="nb">ord</span><span class="p">(</span><span class="s2">"x"</span><span class="p">)))</span>
|
||
<span class="go">None</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-166">如果你想避免上面的<code class="docutils literal"><span class="pre">ord("x")</span></code>调用,你可以设置<code class="xref py py-attr docutils literal"><span class="pre">argtypes</span></code>属性,第二个参数将从单个字符Python字节对象成C字符:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">strchr</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">c_char_p</span>
|
||
<span class="gp">>>> </span><span class="n">strchr</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">c_char_p</span><span class="p">,</span> <span class="n">c_char</span><span class="p">]</span>
|
||
<span class="gp">>>> </span><span class="n">strchr</span><span class="p">(</span><span class="n">b</span><span class="s2">"abcdef"</span><span class="p">,</span> <span class="n">b</span><span class="s2">"d"</span><span class="p">)</span>
|
||
<span class="go">'def'</span>
|
||
<span class="gp">>>> </span><span class="n">strchr</span><span class="p">(</span><span class="n">b</span><span class="s2">"abcdef"</span><span class="p">,</span> <span class="n">b</span><span class="s2">"def"</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
<span class="gr">ArgumentError</span>: <span class="n">argument 2: exceptions.TypeError: one character string expected</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">strchr</span><span class="p">(</span><span class="n">b</span><span class="s2">"abcdef"</span><span class="p">,</span> <span class="n">b</span><span class="s2">"x"</span><span class="p">))</span>
|
||
<span class="go">None</span>
|
||
<span class="gp">>>> </span><span class="n">strchr</span><span class="p">(</span><span class="n">b</span><span class="s2">"abcdef"</span><span class="p">,</span> <span class="n">b</span><span class="s2">"d"</span><span class="p">)</span>
|
||
<span class="go">'def'</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-167">如果外部函数返回一个整数,您也可以使用可调用的Python对象(例如函数或类)作为<code class="xref py py-attr docutils literal"><span class="pre">restype</span></code>属性。</span><span class="yiyi-st" id="yiyi-168">在C函数调用结束后会<em>使用其返回的整数作为参数</em>调用这个Py可调用对象,而其返回值作为函数调用的返回值.</span><span class="yiyi-st" id="yiyi-169">这对检查错误返回值并自动引发异常很有用:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">GetModuleHandle</span> <span class="o">=</span> <span class="n">windll</span><span class="o">.</span><span class="n">kernel32</span><span class="o">.</span><span class="n">GetModuleHandleA</span>
|
||
<span class="gp">>>> </span><span class="k">def</span> <span class="nf">ValidHandle</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">if</span> <span class="n">value</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">raise</span> <span class="n">WinError</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="n">value</span>
|
||
<span class="gp">...</span>
|
||
<span class="go">>>></span>
|
||
<span class="gp">>>> </span><span class="n">GetModuleHandle</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ValidHandle</span>
|
||
<span class="gp">>>> </span><span class="n">GetModuleHandle</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
|
||
<span class="go">486539264</span>
|
||
<span class="gp">>>> </span><span class="n">GetModuleHandle</span><span class="p">(</span><span class="s2">"something silly"</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">3</span>, in <span class="n">ValidHandle</span>
|
||
<span class="gr">OSError</span>: <span class="n">[Errno 126] The specified module could not be found.</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-170"><code class="docutils literal"><span class="pre">WinError</span></code>是一个函数,它将调用Windows <code class="docutils literal"><span class="pre">FormatMessage()</span></code> api来获取错误代码的字符串表示形式,并且<em>返回一个异常。</em></span><span class="yiyi-st" id="yiyi-171"><code class="docutils literal"><span class="pre">WinError</span></code>接受一个可选的错误代码参数,如果没有人使用它,它会调用<a class="reference internal" href="#ctypes.GetLastError" title="ctypes.GetLastError"><code class="xref py py-func docutils literal"><span class="pre">GetLastError()</span></code></a>来检索它。</span></p><p><span class="yiyi-st" id="yiyi-172">请注意,通过<code class="xref py py-attr docutils literal"><span class="pre">errcheck</span></code>属性可以使用更强大的错误检查机制;详情请参阅参考手册。</span></p></div><div class="section" id="passing-pointers-or-passing-parameters-by-reference"><h3><span class="yiyi-st" id="yiyi-173">16.16.1.9. </span><span class="yiyi-st" id="yiyi-174">传递指针或通过引用传递参数</span></h3><p><span class="yiyi-st" id="yiyi-175">有时,一个C api函数期望一个<em>指针</em>作为参数的数据类型,可能想要写入相应的位置,或者因数据太大而无法通过值传递。</span><span class="yiyi-st" id="yiyi-176">这也被称为<em>通过参考</em>传递参数。</span></p><p><span class="yiyi-st" id="yiyi-177"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>导出用于通过引用传递参数的<a class="reference internal" href="#ctypes.byref" title="ctypes.byref"><code class="xref py py-func docutils literal"><span class="pre">byref()</span></code></a>函数。</span><span class="yiyi-st" id="yiyi-178">使用<a class="reference internal" href="#ctypes.pointer" title="ctypes.pointer"><code class="xref py py-func docutils literal"><span class="pre">pointer()</span></code></a>函数可以实现相同的效果,虽然<a class="reference internal" href="#ctypes.pointer" title="ctypes.pointer"><code class="xref py py-func docutils literal"><span class="pre">pointer()</span></code></a>做了很多工作,因为它构造了一个真正的指针对象,因此如果你不需要Python中的指针对象本身,<a class="reference internal" href="#ctypes.byref" title="ctypes.byref"><code class="xref py py-func docutils literal"><span class="pre">byref()</span></code></a>使用起来更快:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">i</span> <span class="o">=</span> <span class="n">c_int</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">f</span> <span class="o">=</span> <span class="n">c_float</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">create_string_buffer</span><span class="p">(</span><span class="n">b</span><span class="s1">'</span><span class="se">\000</span><span class="s1">'</span> <span class="o">*</span> <span class="mi">32</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="o">.</span><span class="n">value</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">value</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">value</span><span class="p">))</span>
|
||
<span class="go">0 0.0 b''</span>
|
||
<span class="gp">>>> </span><span class="n">libc</span><span class="o">.</span><span class="n">sscanf</span><span class="p">(</span><span class="n">b</span><span class="s2">"1 3.14 Hello"</span><span class="p">,</span> <span class="n">b</span><span class="s2">"</span><span class="si">%d</span><span class="s2"> </span><span class="si">%f</span><span class="s2"> </span><span class="si">%s</span><span class="s2">"</span><span class="p">,</span>
|
||
<span class="gp">... </span> <span class="n">byref</span><span class="p">(</span><span class="n">i</span><span class="p">),</span> <span class="n">byref</span><span class="p">(</span><span class="n">f</span><span class="p">),</span> <span class="n">s</span><span class="p">)</span>
|
||
<span class="go">3</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="o">.</span><span class="n">value</span><span class="p">,</span> <span class="n">f</span><span class="o">.</span><span class="n">value</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">s</span><span class="o">.</span><span class="n">value</span><span class="p">))</span>
|
||
<span class="go">1 3.1400001049 b'Hello'</span>
|
||
<span class="go">>>></span>
|
||
</code></pre></div><div class="section" id="structures-and-unions"><h3><span class="yiyi-st" id="yiyi-179">16.16.1.10. </span><span class="yiyi-st" id="yiyi-180">结构体和联合</span></h3><p><span class="yiyi-st" id="yiyi-181">结构和联合必须继承自<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>模块中定义的<a class="reference internal" href="#ctypes.Structure" title="ctypes.Structure"><code class="xref py py-class docutils literal"><span class="pre">Structure</span></code></a>和<a class="reference internal" href="#ctypes.Union" title="ctypes.Union"><code class="xref py py-class docutils literal"><span class="pre">Union</span></code></a>基类。</span><span class="yiyi-st" id="yiyi-182">每个子类都必须定义一个<code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code>属性。</span><span class="yiyi-st" id="yiyi-183"><code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code>必须是包含<em>字段名称</em>和<em>字段类型</em>的<em>2元组</em>的列表。</span></p><p><span class="yiyi-st" id="yiyi-184">字段类型必须是<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>类型,如<a class="reference internal" href="#ctypes.c_int" title="ctypes.c_int"><code class="xref py py-class docutils literal"><span class="pre">c_int</span></code></a>或任何其他派生的<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>类型:结构体,共用体,数组,指针</span></p><p><span class="yiyi-st" id="yiyi-185">下面是一个POINT结构的简单示例,它包含两个名为<em>x</em>和<em>y</em>的整数,并且还演示了如何在构造函数中初始化结构:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes</span> <span class="k">import</span> <span class="o">*</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">POINT</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">_fields_</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">"x"</span><span class="p">,</span> <span class="n">c_int</span><span class="p">),</span>
|
||
<span class="gp">... </span> <span class="p">(</span><span class="s2">"y"</span><span class="p">,</span> <span class="n">c_int</span><span class="p">)]</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">point</span> <span class="o">=</span> <span class="n">POINT</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">20</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">point</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">point</span><span class="o">.</span><span class="n">y</span><span class="p">)</span>
|
||
<span class="go">10 20</span>
|
||
<span class="gp">>>> </span><span class="n">point</span> <span class="o">=</span> <span class="n">POINT</span><span class="p">(</span><span class="n">y</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">point</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">point</span><span class="o">.</span><span class="n">y</span><span class="p">)</span>
|
||
<span class="go">0 5</span>
|
||
<span class="gp">>>> </span><span class="n">POINT</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
<span class="gr">ValueError</span>: <span class="n">too many initializers</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-186">但是,您可以构建更复杂的结构。</span><span class="yiyi-st" id="yiyi-187">通过使用结构作为字段类型,结构本身可以包含其他结构。</span></p><p><span class="yiyi-st" id="yiyi-188">Here is a RECT structure which contains two POINTs named <em>upperleft</em> and <em>lowerright</em>:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">RECT</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">_fields_</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">"upperleft"</span><span class="p">,</span> <span class="n">POINT</span><span class="p">),</span>
|
||
<span class="gp">... </span> <span class="p">(</span><span class="s2">"lowerright"</span><span class="p">,</span> <span class="n">POINT</span><span class="p">)]</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">rc</span> <span class="o">=</span> <span class="n">RECT</span><span class="p">(</span><span class="n">point</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">rc</span><span class="o">.</span><span class="n">upperleft</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">rc</span><span class="o">.</span><span class="n">upperleft</span><span class="o">.</span><span class="n">y</span><span class="p">)</span>
|
||
<span class="go">0 5</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">rc</span><span class="o">.</span><span class="n">lowerright</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">rc</span><span class="o">.</span><span class="n">lowerright</span><span class="o">.</span><span class="n">y</span><span class="p">)</span>
|
||
<span class="go">0 0</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-189">嵌套结构也可以通过几种方式在构造函数中初始化:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">r</span> <span class="o">=</span> <span class="n">RECT</span><span class="p">(</span><span class="n">POINT</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">POINT</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">r</span> <span class="o">=</span> <span class="n">RECT</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">))</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-190">可以从<em>类</em>中检索字段<a class="reference internal" href="../glossary.html#term-descriptor"><span class="xref std std-term">descriptor</span></a>,它们对调试很有用,因为它们可以提供有用的信息:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">POINT</span><span class="o">.</span><span class="n">x</span><span class="p">)</span>
|
||
<span class="go"><Field type=c_long, ofs=0, size=4></span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">POINT</span><span class="o">.</span><span class="n">y</span><span class="p">)</span>
|
||
<span class="go"><Field type=c_long, ofs=4, size=4></span>
|
||
<span class="go">>>></span>
|
||
</code></pre><div class="admonition warning" id="ctypes-structureunion-alignment-byte-order"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-191">警告</span></p><p class="last"><span class="yiyi-st" id="yiyi-192"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a> 不支持以传值方式传递 带位域的共用体或结构体 给函数。</span><span class="yiyi-st" id="yiyi-193">虽然这可能适用于32位x86,但图书馆无法保证在一般情况下工作。</span><span class="yiyi-st" id="yiyi-194">应该始终以指针的形式将带位域的共用体和结构体传递给函数。</span></p></div></div><div class="section" id="structure-union-alignment-and-byte-order"><h3><span class="yiyi-st" id="yiyi-195">16.16.1.11. </span><span class="yiyi-st" id="yiyi-196">结构体/共用体的对齐方式和字节序 </span></h3><p><span class="yiyi-st" id="yiyi-197">默认情况下,Structure和Union字段的对齐方式与C编译器所做的相同。</span><span class="yiyi-st" id="yiyi-198">可以在子类定义中指定<code class="xref py py-attr docutils literal"><span class="pre">_pack_</span></code> class属性来覆盖此行为。</span><span class="yiyi-st" id="yiyi-199">这必须设置为正整数并指定字段的最大对齐方式。</span><span class="yiyi-st" id="yiyi-200">这与在MSVC中<code class="docutils literal"><span class="pre">#pragma</span> <span class="pre">pack(n)</span></code>功能一样</span></p><p><span class="yiyi-st" id="yiyi-201"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>使用结构和联合的本地字节顺序。</span><span class="yiyi-st" id="yiyi-202">To build structures with non-native byte order, you can use one of the <a class="reference internal" href="#ctypes.BigEndianStructure" title="ctypes.BigEndianStructure"><code class="xref py py-class docutils literal"><span class="pre">BigEndianStructure</span></code></a>, <a class="reference internal" href="#ctypes.LittleEndianStructure" title="ctypes.LittleEndianStructure"><code class="xref py py-class docutils literal"><span class="pre">LittleEndianStructure</span></code></a>, <code class="xref py py-class docutils literal"><span class="pre">BigEndianUnion</span></code>, and <code class="xref py py-class docutils literal"><span class="pre">LittleEndianUnion</span></code> base classes. </span><span class="yiyi-st" id="yiyi-203">这些类不能包含指针字段。</span></p></div><div class="section" id="bit-fields-in-structures-and-unions"><h3><span class="yiyi-st" id="yiyi-204">16.16.1.12. </span><span class="yiyi-st" id="yiyi-205">在结构体和联合中的位域</span></h3><p><span class="yiyi-st" id="yiyi-206">可以创建包含位域的结构和联合。</span><span class="yiyi-st" id="yiyi-207">位字段仅适用于整数字段,位宽指定为<code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code>元组中的第三项:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Int</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">_fields_</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">"first_16"</span><span class="p">,</span> <span class="n">c_int</span><span class="p">,</span> <span class="mi">16</span><span class="p">),</span>
|
||
<span class="gp">... </span> <span class="p">(</span><span class="s2">"second_16"</span><span class="p">,</span> <span class="n">c_int</span><span class="p">,</span> <span class="mi">16</span><span class="p">)]</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">Int</span><span class="o">.</span><span class="n">first_16</span><span class="p">)</span>
|
||
<span class="go"><Field type=c_long, ofs=0:0, bits=16></span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">Int</span><span class="o">.</span><span class="n">second_16</span><span class="p">)</span>
|
||
<span class="go"><Field type=c_long, ofs=0:16, bits=16></span>
|
||
<span class="go">>>></span>
|
||
</code></pre></div><div class="section" id="arrays"><h3><span class="yiyi-st" id="yiyi-208">16.16.1.13. </span><span class="yiyi-st" id="yiyi-209">数组</span></h3><p><span class="yiyi-st" id="yiyi-210">数组是序列,包含固定数量的相同类型的实例。</span></p><p><span class="yiyi-st" id="yiyi-211">推荐的创建数组类型的方法是将数据类型乘以正整数:</span></p><pre><code class="language-python"><span></span><span class="n">TenPointsArrayType</span> <span class="o">=</span> <span class="n">POINT</span> <span class="o">*</span> <span class="mi">10</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-212">下面是一个有点人为的数据类型的例子,它是一个包含4个POINT和其他内容的结构:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes</span> <span class="k">import</span> <span class="o">*</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">POINT</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">_fields_</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"x"</span><span class="p">,</span> <span class="n">c_int</span><span class="p">),</span> <span class="p">(</span><span class="s2">"y"</span><span class="p">,</span> <span class="n">c_int</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">MyStruct</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">_fields_</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">"a"</span><span class="p">,</span> <span class="n">c_int</span><span class="p">),</span>
|
||
<span class="gp">... </span> <span class="p">(</span><span class="s2">"b"</span><span class="p">,</span> <span class="n">c_float</span><span class="p">),</span>
|
||
<span class="gp">... </span> <span class="p">(</span><span class="s2">"point_array"</span><span class="p">,</span> <span class="n">POINT</span> <span class="o">*</span> <span class="mi">4</span><span class="p">)]</span>
|
||
<span class="go">>>></span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">MyStruct</span><span class="p">()</span><span class="o">.</span><span class="n">point_array</span><span class="p">))</span>
|
||
<span class="go">4</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-213">实例以通常的方式创建,通过调用该类:</span></p><pre><code class="language-python"><span></span><span class="n">arr</span> <span class="o">=</span> <span class="n">TenPointsArrayType</span><span class="p">()</span>
|
||
<span class="k">for</span> <span class="n">pt</span> <span class="ow">in</span> <span class="n">arr</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="n">pt</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">pt</span><span class="o">.</span><span class="n">y</span><span class="p">)</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-214">上面的代码打印了一系列<code class="docutils literal"><span class="pre">0</span> <span class="pre">0</span></code>行,因为数组内容被初始化为零。</span></p><p><span class="yiyi-st" id="yiyi-215">也可以指定正确类型的初始化程序:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes</span> <span class="k">import</span> <span class="o">*</span>
|
||
<span class="gp">>>> </span><span class="n">TenIntegers</span> <span class="o">=</span> <span class="n">c_int</span> <span class="o">*</span> <span class="mi">10</span>
|
||
<span class="gp">>>> </span><span class="n">ii</span> <span class="o">=</span> <span class="n">TenIntegers</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">ii</span><span class="p">)</span>
|
||
<span class="go"><c_long_Array_10 object at 0x...></span>
|
||
<span class="gp">>>> </span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">ii</span><span class="p">:</span> <span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">" "</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="go">1 2 3 4 5 6 7 8 9 10</span>
|
||
<span class="go">>>></span>
|
||
</code></pre></div><div class="section" id="pointers"><h3><span class="yiyi-st" id="yiyi-216">16.16.1.14. </span><span class="yiyi-st" id="yiyi-217">指针</span></h3><p><span class="yiyi-st" id="yiyi-218">指针实例是通过调用<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>类型的<a class="reference internal" href="#ctypes.pointer" title="ctypes.pointer"><code class="xref py py-func docutils literal"><span class="pre">pointer()</span></code></a>函数创建的:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes</span> <span class="k">import</span> <span class="o">*</span>
|
||
<span class="gp">>>> </span><span class="n">i</span> <span class="o">=</span> <span class="n">c_int</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">pi</span> <span class="o">=</span> <span class="n">pointer</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-219">指针实例具有<a class="reference internal" href="#ctypes._Pointer.contents" title="ctypes._Pointer.contents"><code class="xref py py-attr docutils literal"><span class="pre">contents</span></code></a>属性,该属性返回指针指向的对象,即上面的<code class="docutils literal"><span class="pre">i</span></code>对象:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">pi</span><span class="o">.</span><span class="n">contents</span>
|
||
<span class="go">c_long(42)</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-220">请注意,<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>没有OOR(原始对象返回),它会在您每次检索属性时构造一个新的等效对象:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">pi</span><span class="o">.</span><span class="n">contents</span> <span class="ow">is</span> <span class="n">i</span>
|
||
<span class="go">False</span>
|
||
<span class="gp">>>> </span><span class="n">pi</span><span class="o">.</span><span class="n">contents</span> <span class="ow">is</span> <span class="n">pi</span><span class="o">.</span><span class="n">contents</span>
|
||
<span class="go">False</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-221">为指针的内容属性指派另一个<a class="reference internal" href="#ctypes.c_int" title="ctypes.c_int"><code class="xref py py-class docutils literal"><span class="pre">c_int</span></code></a>实例会导致指针指向存储它的内存位置:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">i</span> <span class="o">=</span> <span class="n">c_int</span><span class="p">(</span><span class="mi">99</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">pi</span><span class="o">.</span><span class="n">contents</span> <span class="o">=</span> <span class="n">i</span>
|
||
<span class="gp">>>> </span><span class="n">pi</span><span class="o">.</span><span class="n">contents</span>
|
||
<span class="go">c_long(99)</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-222">指针实例也可以用整数索引:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">pi</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||
<span class="go">99</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-223">分配给整数索引会改变指向的值:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
|
||
<span class="go">c_long(99)</span>
|
||
<span class="gp">>>> </span><span class="n">pi</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">22</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
|
||
<span class="go">c_long(22)</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-224">也可以使用不同于0的索引,但是您必须知道自己在做什么,就像在C中一样:您可以访问或更改任意内存位置。</span><span class="yiyi-st" id="yiyi-225">Generally you only use this feature if you receive a pointer from a C function, and you <em>know</em> that the pointer actually points to an array instead of a single item.</span></p><p><span class="yiyi-st" id="yiyi-226">在幕后,<a class="reference internal" href="#ctypes.pointer" title="ctypes.pointer"><code class="xref py py-func docutils literal"><span class="pre">pointer()</span></code></a>函数不仅仅是创建指针实例,它必须首先创建指针<em>types</em>。</span><span class="yiyi-st" id="yiyi-227">这是通过<a class="reference internal" href="#ctypes.POINTER" title="ctypes.POINTER"><code class="xref py py-func docutils literal"><span class="pre">POINTER()</span></code></a>函数完成的,该函数接受任何<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>类型,并返回一个新类型:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">PI</span> <span class="o">=</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">c_int</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">PI</span>
|
||
<span class="go"><class 'ctypes.LP_c_long'></span>
|
||
<span class="gp">>>> </span><span class="n">PI</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
<span class="gr">TypeError</span>: <span class="n">expected c_long instead of int</span>
|
||
<span class="gp">>>> </span><span class="n">PI</span><span class="p">(</span><span class="n">c_int</span><span class="p">(</span><span class="mi">42</span><span class="p">))</span>
|
||
<span class="go"><ctypes.LP_c_long object at 0x...></span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-228">调用不带参数的指针类型将创建一个<code class="docutils literal"><span class="pre">NULL</span></code>指针。</span><span class="yiyi-st" id="yiyi-229"><code class="docutils literal"><span class="pre">NULL</span></code>指针具有<code class="docutils literal"><span class="pre">False</span></code>布尔值:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">null_ptr</span> <span class="o">=</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">c_int</span><span class="p">)()</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="nb">bool</span><span class="p">(</span><span class="n">null_ptr</span><span class="p">))</span>
|
||
<span class="go">False</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-230"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a> checks for <code class="docutils literal"><span class="pre">NULL</span></code> when dereferencing pointers (but dereferencing invalid non-<code class="docutils literal"><span class="pre">NULL</span></code> pointers would crash Python):</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">null_ptr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="o">....</span>
|
||
<span class="gr">ValueError</span>: <span class="n">NULL pointer access</span>
|
||
<span class="go">>>></span>
|
||
|
||
<span class="gp">>>> </span><span class="n">null_ptr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1234</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="o">....</span>
|
||
<span class="gr">ValueError</span>: <span class="n">NULL pointer access</span>
|
||
<span class="go">>>></span>
|
||
</code></pre></div><div class="section" id="type-conversions"><h3><span class="yiyi-st" id="yiyi-231">16.16.1.15. </span><span class="yiyi-st" id="yiyi-232">类型约定</span></h3><p><span class="yiyi-st" id="yiyi-233">通常,ctypes会进行严格的类型检查。</span><span class="yiyi-st" id="yiyi-234">这意味着,如果在函数的<code class="xref py py-attr docutils literal"><span class="pre">argtypes</span></code>列表中有<code class="docutils literal"><span class="pre">POINTER(c_int)</span></code>,或者在结构体定义中作为成员字段的类型,则实参只能接受相同类型的实例。</span><span class="yiyi-st" id="yiyi-235">这个规则有一些例外,其中ctypes接受其他对象。</span><span class="yiyi-st" id="yiyi-236">例如,您可以传递兼容的数组实例而不是指针类型。</span><span class="yiyi-st" id="yiyi-237">因此,对于<code class="docutils literal"><span class="pre">POINTER(c_int)</span></code>,ctypes接受一个c_int数组:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">Bar</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">_fields_</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">"count"</span><span class="p">,</span> <span class="n">c_int</span><span class="p">),</span> <span class="p">(</span><span class="s2">"values"</span><span class="p">,</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">c_int</span><span class="p">))]</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">bar</span> <span class="o">=</span> <span class="n">Bar</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">bar</span><span class="o">.</span><span class="n">values</span> <span class="o">=</span> <span class="p">(</span><span class="n">c_int</span> <span class="o">*</span> <span class="mi">3</span><span class="p">)(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">bar</span><span class="o">.</span><span class="n">count</span> <span class="o">=</span> <span class="mi">3</span>
|
||
<span class="gp">>>> </span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">bar</span><span class="o">.</span><span class="n">count</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">bar</span><span class="o">.</span><span class="n">values</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
|
||
<span class="gp">...</span>
|
||
<span class="go">1</span>
|
||
<span class="go">2</span>
|
||
<span class="go">3</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-238">另外,如果函数参数在<code class="xref py py-attr docutils literal"><span class="pre">argtypes</span></code>中显式声明为指针类型(例如<code class="docutils literal"><span class="pre">POINTER(c_int)</span></code>),则指向类型的对象(<code class="docutils literal"><span class="pre">c_int</span></code>)可以传递给函数。</span><span class="yiyi-st" id="yiyi-239">在这种情况下,ctypes将自动应用所需的<a class="reference internal" href="#ctypes.byref" title="ctypes.byref"><code class="xref py py-func docutils literal"><span class="pre">byref()</span></code></a>转换。</span></p><p><span class="yiyi-st" id="yiyi-240">要将POINTER类型字段设置为<code class="docutils literal"><span class="pre">NULL</span></code>,您可以分配<code class="docutils literal"><span class="pre">None</span></code>:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">bar</span><span class="o">.</span><span class="n">values</span> <span class="o">=</span> <span class="kc">None</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-241">有时你有不兼容类型的实例。</span><span class="yiyi-st" id="yiyi-242">在C中,您可以将一种类型转换为另一种类型。</span><span class="yiyi-st" id="yiyi-243"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>提供了一个可以以相同方式使用的<a class="reference internal" href="#ctypes.cast" title="ctypes.cast"><code class="xref py py-func docutils literal"><span class="pre">cast()</span></code></a>函数。</span><span class="yiyi-st" id="yiyi-244">上面定义的<code class="docutils literal"><span class="pre">Bar</span></code>结构为其<code class="docutils literal"><span class="pre">values</span></code>字段接受<code class="docutils literal"><span class="pre">POINTER(c_int)</span></code>指针或<a class="reference internal" href="#ctypes.c_int" title="ctypes.c_int"><code class="xref py py-class docutils literal"><span class="pre">c_int</span></code></a>数组,但不接受实例其他类型:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">bar</span><span class="o">.</span><span class="n">values</span> <span class="o">=</span> <span class="p">(</span><span class="n">c_byte</span> <span class="o">*</span> <span class="mi">4</span><span class="p">)()</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
<span class="gr">TypeError</span>: <span class="n">incompatible types, c_byte_Array_4 instance instead of LP_c_long instance</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-245">对于这些情况,<a class="reference internal" href="#ctypes.cast" title="ctypes.cast"><code class="xref py py-func docutils literal"><span class="pre">cast()</span></code></a>函数很方便。</span></p><p><span class="yiyi-st" id="yiyi-246">可以使用<a class="reference internal" href="#ctypes.cast" title="ctypes.cast"><code class="xref py py-func docutils literal"><span class="pre">cast()</span></code></a>函数将ctypes实例转换为指向不同ctypes数据类型的指针。</span><span class="yiyi-st" id="yiyi-247"><a class="reference internal" href="#ctypes.cast" title="ctypes.cast"><code class="xref py py-func docutils literal"><span class="pre">cast()</span></code></a>有两个参数,一个可以转换为某种类型的指针的ctypes对象,以及一个ctypes指针类型。</span><span class="yiyi-st" id="yiyi-248">它返回第二个参数的一个实例,它引用与第一个参数相同的内存块:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="n">c_byte</span> <span class="o">*</span> <span class="mi">4</span><span class="p">)()</span>
|
||
<span class="gp">>>> </span><span class="n">cast</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">c_int</span><span class="p">))</span>
|
||
<span class="go"><ctypes.LP_c_long object at ...></span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-249">因此,可以使用<a class="reference internal" href="#ctypes.cast" title="ctypes.cast"><code class="xref py py-func docutils literal"><span class="pre">cast()</span></code></a>指定<code class="docutils literal"><span class="pre">Bar</span></code>的<code class="docutils literal"><span class="pre">values</span></code>字段的结构:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">bar</span> <span class="o">=</span> <span class="n">Bar</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">bar</span><span class="o">.</span><span class="n">values</span> <span class="o">=</span> <span class="n">cast</span><span class="p">((</span><span class="n">c_byte</span> <span class="o">*</span> <span class="mi">4</span><span class="p">)(),</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">c_int</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">bar</span><span class="o">.</span><span class="n">values</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
||
<span class="go">0</span>
|
||
<span class="go">>>></span>
|
||
</code></pre></div><div class="section" id="incomplete-types"><h3><span class="yiyi-st" id="yiyi-250">16.16.1.16. </span><span class="yiyi-st" id="yiyi-251">函数回调</span></h3><p><span class="yiyi-st" id="yiyi-252"><em>不完全类型</em>是其成员尚未指定的结构,联合或数组。</span><span class="yiyi-st" id="yiyi-253">在C中,它们由后面定义的前向声明指定:</span></p><pre><code class="language-python"><span></span><span class="n">struct</span> <span class="n">cell</span><span class="p">;</span> <span class="o">/*</span> <span class="n">forward</span> <span class="n">declaration</span> <span class="o">*/</span>
|
||
|
||
<span class="n">struct</span> <span class="n">cell</span> <span class="p">{</span>
|
||
<span class="n">char</span> <span class="o">*</span><span class="n">name</span><span class="p">;</span>
|
||
<span class="n">struct</span> <span class="n">cell</span> <span class="o">*</span><span class="nb">next</span><span class="p">;</span>
|
||
<span class="p">};</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-254">直接翻译成ctypes代码就是这样,但它不起作用:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="k">class</span> <span class="nc">cell</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">_fields_</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">"name"</span><span class="p">,</span> <span class="n">c_char_p</span><span class="p">),</span>
|
||
<span class="gp">... </span> <span class="p">(</span><span class="s2">"next"</span><span class="p">,</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">cell</span><span class="p">))]</span>
|
||
<span class="gp">...</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n">?</span>
|
||
File <span class="nb">"<stdin>"</span>, line <span class="m">2</span>, in <span class="n">cell</span>
|
||
<span class="gr">NameError</span>: <span class="n">name 'cell' is not defined</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-255">因为新的<code class="docutils literal"><span class="pre">类</span> <span class="pre">cell</span></code>在类语句本身中不可用。</span><span class="yiyi-st" id="yiyi-256">在<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>中,我们可以定义<code class="docutils literal"><span class="pre">cell</span></code>类,并在稍后的class声明之后设置<code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code>属性:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes</span> <span class="k">import</span> <span class="o">*</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">cell</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">pass</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">cell</span><span class="o">.</span><span class="n">_fields_</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">"name"</span><span class="p">,</span> <span class="n">c_char_p</span><span class="p">),</span>
|
||
<span class="gp">... </span> <span class="p">(</span><span class="s2">"next"</span><span class="p">,</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">cell</span><span class="p">))]</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-257">让我们尝试一下。</span><span class="yiyi-st" id="yiyi-258">我们创建了<code class="docutils literal"><span class="pre">cell</span></code>的两个实例,让它们指向对方,最后跟随指针链几次:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">c1</span> <span class="o">=</span> <span class="n">cell</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">c1</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="s2">"foo"</span>
|
||
<span class="gp">>>> </span><span class="n">c2</span> <span class="o">=</span> <span class="n">cell</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">c2</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="s2">"bar"</span>
|
||
<span class="gp">>>> </span><span class="n">c1</span><span class="o">.</span><span class="n">next</span> <span class="o">=</span> <span class="n">pointer</span><span class="p">(</span><span class="n">c2</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">c2</span><span class="o">.</span><span class="n">next</span> <span class="o">=</span> <span class="n">pointer</span><span class="p">(</span><span class="n">c1</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">p</span> <span class="o">=</span> <span class="n">c1</span>
|
||
<span class="gp">>>> </span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">8</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">" "</span><span class="p">)</span>
|
||
<span class="gp">... </span> <span class="n">p</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||
<span class="gp">...</span>
|
||
<span class="go">foo bar foo bar foo bar foo bar</span>
|
||
<span class="go">>>></span>
|
||
</code></pre></div><div class="section" id="callback-functions"><h3><span class="yiyi-st" id="yiyi-259">16.16.1.17. </span><span class="yiyi-st" id="yiyi-260">函数回调</span></h3><p><span class="yiyi-st" id="yiyi-261"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>允许从Python可调用对象中创建C可调用函数指针。</span><span class="yiyi-st" id="yiyi-262">这些有时称为<em>回调函数</em>。</span></p><p><span class="yiyi-st" id="yiyi-263">首先,您必须为回调函数创建一个类。</span><span class="yiyi-st" id="yiyi-264">该类知道调用约定,返回类型以及此函数将接收的参数的数量和类型。</span></p><p><span class="yiyi-st" id="yiyi-265"><a class="reference internal" href="#ctypes.CFUNCTYPE" title="ctypes.CFUNCTYPE"><code class="xref py py-func docutils literal"><span class="pre">CFUNCTYPE()</span></code></a>工厂函数使用<code class="docutils literal"><span class="pre">cdecl</span></code>调用约定为回调函数创建类型。</span><span class="yiyi-st" id="yiyi-266">在Windows上,<a class="reference internal" href="#ctypes.WINFUNCTYPE" title="ctypes.WINFUNCTYPE"><code class="xref py py-func docutils literal"><span class="pre">WINFUNCTYPE()</span></code></a>工厂函数使用<code class="docutils literal"><span class="pre">stdcall</span></code>调用约定为回调函数创建类型。</span></p><p><span class="yiyi-st" id="yiyi-267">这两个工厂函数都是以结果类型作为第一个参数来调用的,而回调函数期望的参数类型作为剩余的参数。</span></p><p><span class="yiyi-st" id="yiyi-268">我将在这里展示一个使用标准C库的<code class="xref c c-func docutils literal"><span class="pre">qsort()</span></code>函数的示例,该函数用于通过回调函数对项目进行排序。</span><span class="yiyi-st" id="yiyi-269"><code class="xref c c-func docutils literal"><span class="pre">qsort()</span></code> will be used to sort an array of integers:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">IntArray5</span> <span class="o">=</span> <span class="n">c_int</span> <span class="o">*</span> <span class="mi">5</span>
|
||
<span class="gp">>>> </span><span class="n">ia</span> <span class="o">=</span> <span class="n">IntArray5</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">33</span><span class="p">,</span> <span class="mi">99</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">qsort</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">qsort</span>
|
||
<span class="gp">>>> </span><span class="n">qsort</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="kc">None</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-270"><code class="xref py py-func docutils literal"><span class="pre">qsort()</span></code> must be called with a pointer to the data to sort, the number of items in the data array, the size of one item, and a pointer to the comparison function, the callback. </span><span class="yiyi-st" id="yiyi-271">这个回调函数将被两个指向项目的指针调用,如果第一个项目小于第二个项目,它必须返回一个负整数,如果它们相等则返回一个零,否则返回一个正整数。</span></p><p><span class="yiyi-st" id="yiyi-272">所以我们的回调函数接收指向整数的指针,并且必须返回一个整数。</span><span class="yiyi-st" id="yiyi-273">首先我们为回调函数创建<code class="docutils literal"><span class="pre">type</span></code>:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">CMPFUNC</span> <span class="o">=</span> <span class="n">CFUNCTYPE</span><span class="p">(</span><span class="n">c_int</span><span class="p">,</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">c_int</span><span class="p">),</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">c_int</span><span class="p">))</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-274">要开始,下面是一个简单的回调,它显示了它传递的值:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="k">def</span> <span class="nf">py_cmp_func</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"py_cmp_func"</span><span class="p">,</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="mi">0</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">cmp_func</span> <span class="o">=</span> <span class="n">CMPFUNC</span><span class="p">(</span><span class="n">py_cmp_func</span><span class="p">)</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-275">结果:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">qsort</span><span class="p">(</span><span class="n">ia</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">ia</span><span class="p">),</span> <span class="n">sizeof</span><span class="p">(</span><span class="n">c_int</span><span class="p">),</span> <span class="n">cmp_func</span><span class="p">)</span>
|
||
<span class="go">py_cmp_func 5 1</span>
|
||
<span class="go">py_cmp_func 33 99</span>
|
||
<span class="go">py_cmp_func 7 33</span>
|
||
<span class="go">py_cmp_func 5 7</span>
|
||
<span class="go">py_cmp_func 1 7</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-276">现在我们可以比较这两个项目并返回一个有用的结果:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="k">def</span> <span class="nf">py_cmp_func</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s2">"py_cmp_func"</span><span class="p">,</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||
<span class="gp">...</span>
|
||
<span class="go">>>></span>
|
||
<span class="gp">>>> </span><span class="n">qsort</span><span class="p">(</span><span class="n">ia</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">ia</span><span class="p">),</span> <span class="n">sizeof</span><span class="p">(</span><span class="n">c_int</span><span class="p">),</span> <span class="n">CMPFUNC</span><span class="p">(</span><span class="n">py_cmp_func</span><span class="p">))</span>
|
||
<span class="go">py_cmp_func 5 1</span>
|
||
<span class="go">py_cmp_func 33 99</span>
|
||
<span class="go">py_cmp_func 7 33</span>
|
||
<span class="go">py_cmp_func 1 7</span>
|
||
<span class="go">py_cmp_func 5 7</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-277">正如我们可以轻松检查,我们的数组现在排序:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">ia</span><span class="p">:</span> <span class="nb">print</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">" "</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="go">1 5 7 33 99</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><div class="admonition note"><p class="first admonition-title"><span class="yiyi-st" id="yiyi-278">注意</span></p><p><span class="yiyi-st" id="yiyi-279">只要从C代码中使用它们,确保保持对<a class="reference internal" href="#ctypes.CFUNCTYPE" title="ctypes.CFUNCTYPE"><code class="xref py py-func docutils literal"><span class="pre">CFUNCTYPE()</span></code></a>对象的引用。</span><span class="yiyi-st" id="yiyi-280"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>不会,如果你不这样做,它们可能会被垃圾收集,在回调时崩溃你的程序。</span></p><p class="last"><span class="yiyi-st" id="yiyi-281">另外,请注意,如果在Python控制之外创建的线程中调用回调函数(例如,</span><span class="yiyi-st" id="yiyi-282">通过调用回调的外部代码),ctypes在每次调用时创建一个新的虚拟Python线程。</span><span class="yiyi-st" id="yiyi-283">This behavior is correct for most purposes, but it means that values stored with <a class="reference internal" href="threading.html#threading.local" title="threading.local"><code class="xref py py-class docutils literal"><span class="pre">threading.local</span></code></a> will <em>not</em> survive across different callbacks, even when those calls are made from the same C thread.</span></p></div></div><div class="section" id="accessing-values-exported-from-dlls"><h3><span class="yiyi-st" id="yiyi-284">16.16.1.18. </span><span class="yiyi-st" id="yiyi-285">对dlls导出值的访问</span></h3><p><span class="yiyi-st" id="yiyi-286">一些共享库不仅可以导出函数,还可以导出变量。</span><span class="yiyi-st" id="yiyi-287">Python库本身的例子是<code class="xref c c-data docutils literal"><span class="pre">Py_OptimizeFlag</span></code>,一个整数设置为0,1或2,取决于<a class="reference internal" href="../using/cmdline.html#cmdoption-O"><code class="xref std std-option docutils literal"><span class="pre">-O</span></code></a>或<a class="reference internal" href="../using/cmdline.html#cmdoption-OO"><code class="xref std std-option docutils literal"><span class="pre">-OO</span></code></a></span></p><p><span class="yiyi-st" id="yiyi-288"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>可以使用类型的<code class="xref py py-meth docutils literal"><span class="pre">in_dll()</span></code>类方法访问像这样的值。</span><span class="yiyi-st" id="yiyi-289"><em>pythonapi</em>是一个预定义的符号,可以访问Python C api:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">opt_flag</span> <span class="o">=</span> <span class="n">c_int</span><span class="o">.</span><span class="n">in_dll</span><span class="p">(</span><span class="n">pythonapi</span><span class="p">,</span> <span class="s2">"Py_OptimizeFlag"</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">opt_flag</span><span class="p">)</span>
|
||
<span class="go">c_long(0)</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-290">如果解释器启动带有 <a class="reference internal" href="../using/cmdline.html#cmdoption-O"><code class="xref std std-option docutils literal"><span class="pre">-O</span></code></a>, 这个例子会打印<code class="docutils literal"><span class="pre">c_long(1)</span></code>, 或者打印 <code class="docutils literal"><span class="pre">c_long(2)</span></code> 如果指定/(带有) <a class="reference internal" href="../using/cmdline.html#cmdoption-OO"><code class="xref std std-option docutils literal"><span class="pre">-OO</span></code></a> 。</span></p><p><span class="yiyi-st" id="yiyi-291">一个扩展的例子也演示了如何使用指针来访问由Python导出的<a class="reference internal" href="../c-api/import.html#c.PyImport_FrozenModules" title="PyImport_FrozenModules"><code class="xref c c-data docutils literal"><span class="pre">PyImport_FrozenModules</span></code></a>指针。</span></p><p><span class="yiyi-st" id="yiyi-292">引用该价值的文档:</span></p><span class="yiyi-st" id="yiyi-300"><blockquote><div>This pointer is initialized to point to an array of <code class="xref c c-type docutils literal"><span class="pre">struct</span> <span class="pre">_frozen</span></code> records, terminated by one whose members are all <em>NULL</em> or zero. When a frozen module is imported, it is searched in this table. 第三方代码可以利用此技巧提供一个动态创建的静态模块集合.</div></blockquote></span><p><span class="yiyi-st" id="yiyi-293">所以操纵这个指针甚至可以证明是有用的。</span><span class="yiyi-st" id="yiyi-294">要限制示例大小,我们只显示如何使用<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>读取此表:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes</span> <span class="k">import</span> <span class="o">*</span>
|
||
<span class="go">>>></span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">struct_frozen</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">_fields_</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">"name"</span><span class="p">,</span> <span class="n">c_char_p</span><span class="p">),</span>
|
||
<span class="gp">... </span> <span class="p">(</span><span class="s2">"code"</span><span class="p">,</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">c_ubyte</span><span class="p">)),</span>
|
||
<span class="gp">... </span> <span class="p">(</span><span class="s2">"size"</span><span class="p">,</span> <span class="n">c_int</span><span class="p">)]</span>
|
||
<span class="gp">...</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-295">我们已经定义了<code class="xref c c-type docutils literal"><span class="pre">struct</span> <span class="pre">_frozen</span></code>数据类型,所以我们可以得到指向表的指针:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">FrozenTable</span> <span class="o">=</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">struct_frozen</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">table</span> <span class="o">=</span> <span class="n">FrozenTable</span><span class="o">.</span><span class="n">in_dll</span><span class="p">(</span><span class="n">pythonapi</span><span class="p">,</span> <span class="s2">"PyImport_FrozenModules"</span><span class="p">)</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-296">由于<code class="docutils literal"><span class="pre">table</span></code>是<code class="docutils literal"><span class="pre">pointer</span></code>到<code class="docutils literal"><span class="pre">struct_frozen</span></code>数组,我们可以迭代它,但我们需要确保我们的循环终止,因为指针没有指明大小。</span><span class="yiyi-st" id="yiyi-297">迟早它可能会因访问冲突或其他原因而崩溃,所以最好在我们敲入NULL条目时跳出循环:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">table</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">name</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">break</span>
|
||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s2">"ascii"</span><span class="p">),</span> <span class="n">item</span><span class="o">.</span><span class="n">size</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="go">_frozen_importlib 31764</span>
|
||
<span class="go">_frozen_importlib_external 41499</span>
|
||
<span class="go">__hello__ 161</span>
|
||
<span class="go">__phello__ -161</span>
|
||
<span class="go">__phello__.spam 161</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-298">标准Python有一个冻结模块和一个冻结包(由负大小成员表示)的事实并不为人所熟知,它仅用于测试。</span><span class="yiyi-st" id="yiyi-299">例如,试用<code class="docutils literal"><span class="pre">import</span> <span class="pre">__ hello __</span></code>。</span></p></div><div class="section" id="surprises"><h3><span class="yiyi-st" id="yiyi-301">16.16.1.19. </span><span class="yiyi-st" id="yiyi-302">意外</span></h3><p><span class="yiyi-st" id="yiyi-303">在<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>中有一些边缘,您可能会期望除实际发生的情况之外的其他事物。</span></p><p><span class="yiyi-st" id="yiyi-304">考虑下面的例子:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes</span> <span class="k">import</span> <span class="o">*</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">POINT</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">_fields_</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"x"</span><span class="p">,</span> <span class="n">c_int</span><span class="p">),</span> <span class="p">(</span><span class="s2">"y"</span><span class="p">,</span> <span class="n">c_int</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">RECT</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="n">_fields_</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"a"</span><span class="p">,</span> <span class="n">POINT</span><span class="p">),</span> <span class="p">(</span><span class="s2">"b"</span><span class="p">,</span> <span class="n">POINT</span><span class="p">)</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">p1</span> <span class="o">=</span> <span class="n">POINT</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">p2</span> <span class="o">=</span> <span class="n">POINT</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">rc</span> <span class="o">=</span> <span class="n">RECT</span><span class="p">(</span><span class="n">p1</span><span class="p">,</span> <span class="n">p2</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">rc</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">rc</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">y</span><span class="p">,</span> <span class="n">rc</span><span class="o">.</span><span class="n">b</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">rc</span><span class="o">.</span><span class="n">b</span><span class="o">.</span><span class="n">y</span><span class="p">)</span>
|
||
<span class="go">1 2 3 4</span>
|
||
<span class="gp">>>> </span><span class="c1"># now swap the two points</span>
|
||
<span class="gp">>>> </span><span class="n">rc</span><span class="o">.</span><span class="n">a</span><span class="p">,</span> <span class="n">rc</span><span class="o">.</span><span class="n">b</span> <span class="o">=</span> <span class="n">rc</span><span class="o">.</span><span class="n">b</span><span class="p">,</span> <span class="n">rc</span><span class="o">.</span><span class="n">a</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">rc</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">rc</span><span class="o">.</span><span class="n">a</span><span class="o">.</span><span class="n">y</span><span class="p">,</span> <span class="n">rc</span><span class="o">.</span><span class="n">b</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">rc</span><span class="o">.</span><span class="n">b</span><span class="o">.</span><span class="n">y</span><span class="p">)</span>
|
||
<span class="go">3 4 3 4</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-305">嗯。</span><span class="yiyi-st" id="yiyi-306">We certainly expected the last statement to print <code class="docutils literal"><span class="pre">3</span> <span class="pre">4</span> <span class="pre">1</span> <span class="pre">2</span></code>. </span><span class="yiyi-st" id="yiyi-307">发生了什么?</span><span class="yiyi-st" id="yiyi-308">Here are the steps of the <code class="docutils literal"><span class="pre">rc.a,</span> <span class="pre">rc.b</span> <span class="pre">=</span> <span class="pre">rc.b,</span> <span class="pre">rc.a</span></code> line above:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">temp0</span><span class="p">,</span> <span class="n">temp1</span> <span class="o">=</span> <span class="n">rc</span><span class="o">.</span><span class="n">b</span><span class="p">,</span> <span class="n">rc</span><span class="o">.</span><span class="n">a</span>
|
||
<span class="gp">>>> </span><span class="n">rc</span><span class="o">.</span><span class="n">a</span> <span class="o">=</span> <span class="n">temp0</span>
|
||
<span class="gp">>>> </span><span class="n">rc</span><span class="o">.</span><span class="n">b</span> <span class="o">=</span> <span class="n">temp1</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-309">Note that <code class="docutils literal"><span class="pre">temp0</span></code> and <code class="docutils literal"><span class="pre">temp1</span></code> are objects still using the internal buffer of the <code class="docutils literal"><span class="pre">rc</span></code> object above. </span><span class="yiyi-st" id="yiyi-310">So executing <code class="docutils literal"><span class="pre">rc.a</span> <span class="pre">=</span> <span class="pre">temp0</span></code> copies the buffer contents of <code class="docutils literal"><span class="pre">temp0</span></code> into <code class="docutils literal"><span class="pre">rc</span></code> ‘s buffer. </span><span class="yiyi-st" id="yiyi-311">这又反过来改变了<code class="docutils literal"><span class="pre">temp1</span></code>的内容。</span><span class="yiyi-st" id="yiyi-312">所以,最后一个分配<code class="docutils literal"><span class="pre">rc.b</span> <span class="pre">=</span> <span class="pre">temp1</span></code>,没有预期的效果。</span></p><p><span class="yiyi-st" id="yiyi-313">请记住,从Structure,Unions和Arrays中检索子对象不会<em>复制</em>子对象,而是检索访问根对象的基础缓冲区的包装对象。</span></p><p><span class="yiyi-st" id="yiyi-314">另一个可能与预期不同的例子是:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="n">c_char_p</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">s</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="s2">"abc def ghi"</span>
|
||
<span class="gp">>>> </span><span class="n">s</span><span class="o">.</span><span class="n">value</span>
|
||
<span class="go">'abc def ghi'</span>
|
||
<span class="gp">>>> </span><span class="n">s</span><span class="o">.</span><span class="n">value</span> <span class="ow">is</span> <span class="n">s</span><span class="o">.</span><span class="n">value</span>
|
||
<span class="go">False</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-315">为什么要打印<code class="docutils literal"><span class="pre">False</span></code>?</span><span class="yiyi-st" id="yiyi-316">ctypes实例是包含一个内存块和一些访问内存内容的<a class="reference internal" href="../glossary.html#term-descriptor"><span class="xref std std-term">descriptor</span></a>的对象。</span><span class="yiyi-st" id="yiyi-317">在存储器块中存储Python对象不会存储对象本身,而是存储对象的<code class="docutils literal"><span class="pre">contents</span></code>。</span><span class="yiyi-st" id="yiyi-318">每次访问内容都会构造一个新的Python对象!</span></p></div><div class="section" id="variable-sized-data-types"><h3><span class="yiyi-st" id="yiyi-319">16.16.1.20. </span><span class="yiyi-st" id="yiyi-320">可变大小的数据类型</span></h3><p><span class="yiyi-st" id="yiyi-321"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>为可变大小的数组和结构提供了一些支持。</span></p><p><span class="yiyi-st" id="yiyi-322">可以使用<a class="reference internal" href="#ctypes.resize" title="ctypes.resize"><code class="xref py py-func docutils literal"><span class="pre">resize()</span></code></a>函数调整现有ctypes对象的内存缓冲区大小。</span><span class="yiyi-st" id="yiyi-323">该函数将对象作为第一个参数,并将请求的大小以字节为第二个参数。</span><span class="yiyi-st" id="yiyi-324">内存块不能小于由对象类型指定的自然内存块,如果尝试这样做,会引发<a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal"><span class="pre">ValueError</span></code></a>:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">short_array</span> <span class="o">=</span> <span class="p">(</span><span class="n">c_short</span> <span class="o">*</span> <span class="mi">4</span><span class="p">)()</span>
|
||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">sizeof</span><span class="p">(</span><span class="n">short_array</span><span class="p">))</span>
|
||
<span class="go">8</span>
|
||
<span class="gp">>>> </span><span class="n">resize</span><span class="p">(</span><span class="n">short_array</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="o">...</span>
|
||
<span class="gr">ValueError</span>: <span class="n">minimum size is 8</span>
|
||
<span class="gp">>>> </span><span class="n">resize</span><span class="p">(</span><span class="n">short_array</span><span class="p">,</span> <span class="mi">32</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">sizeof</span><span class="p">(</span><span class="n">short_array</span><span class="p">)</span>
|
||
<span class="go">32</span>
|
||
<span class="gp">>>> </span><span class="n">sizeof</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">short_array</span><span class="p">))</span>
|
||
<span class="go">8</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-325">这很好,但是如何访问此数组中包含的其他元素?</span><span class="yiyi-st" id="yiyi-326">由于type仍然只知道大约4个元素,我们得到访问其他元素的错误:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">short_array</span><span class="p">[:]</span>
|
||
<span class="go">[0, 0, 0, 0]</span>
|
||
<span class="gp">>>> </span><span class="n">short_array</span><span class="p">[</span><span class="mi">7</span><span class="p">]</span>
|
||
<span class="gt">Traceback (most recent call last):</span>
|
||
<span class="o">...</span>
|
||
<span class="gr">IndexError</span>: <span class="n">invalid index</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-327">另一种使用<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>的可变大小的数据类型的方法是使用Python的动态特性,并且在需要的大小已知之后(重新)定义数据类型,以个案为基础。</span></p></div></div><div class="section" id="ctypes-reference"><h2><span class="yiyi-st" id="yiyi-328">16.16.2. ctypes参考</span></h2><div class="section" id="finding-shared-libraries"><h3><span class="yiyi-st" id="yiyi-329">16.16.2.1. </span><span class="yiyi-st" id="yiyi-330">查找共享库</span></h3><p><span class="yiyi-st" id="yiyi-331">以编译语言编程时,在编译/链接程序和程序运行时访问共享库。</span></p><p><span class="yiyi-st" id="yiyi-332"><code class="xref py py-func docutils literal"><span class="pre">find_library()</span></code>函数的用途是以类似于编译器的方式来定位库(在具有多个版本的共享库的平台上最近应该加载),而ctypes库加载程序就像程序运行时一样,直接调用运行时加载程序。</span></p><p><span class="yiyi-st" id="yiyi-333"><code class="xref py py-mod docutils literal"><span class="pre">ctypes.util</span></code>模块提供了一个函数,可以帮助确定要加载的库。</span></p><dl class="data"><dt><span class="yiyi-st" id="yiyi-334"> <code class="descclassname">ctypes.util.</code><code class="descname">find_library</code><span class="sig-paren">(</span><em>name</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-335">尝试找到一个库并返回一个路径名。</span><span class="yiyi-st" id="yiyi-336"><em>name</em>是不带任何前缀(如<em>lib</em>),库后缀<code class="docutils literal"><span class="pre">.so</span></code>,<code class="docutils literal"><span class="pre">.dylib</span></code>或版本号这是用于posix链接器选项<a class="reference internal" href="tarfile.html#cmdoption-l"><code class="xref std std-option docutils literal"><span class="pre">-l</span></code></a></span><span class="yiyi-st" id="yiyi-337">如果没有找到库,则返回<code class="docutils literal"><span class="pre">None</span></code>。</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-338">确切的功能依赖于系统。</span></p><p><span class="yiyi-st" id="yiyi-339">在Linux上,<code class="xref py py-func docutils literal"><span class="pre">find_library()</span></code>尝试运行外部程序(<code class="docutils literal"><span class="pre">/sbin/ldconfig</span></code>,<code class="docutils literal"><span class="pre">gcc</span></code>和<code class="docutils literal"><span class="pre">objdump</span></code>)找到库文件。</span><span class="yiyi-st" id="yiyi-340">它返回库文件的文件名。</span><span class="yiyi-st" id="yiyi-341">这里有些例子:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes.util</span> <span class="k">import</span> <span class="n">find_library</span>
|
||
<span class="gp">>>> </span><span class="n">find_library</span><span class="p">(</span><span class="s2">"m"</span><span class="p">)</span>
|
||
<span class="go">'libm.so.6'</span>
|
||
<span class="gp">>>> </span><span class="n">find_library</span><span class="p">(</span><span class="s2">"c"</span><span class="p">)</span>
|
||
<span class="go">'libc.so.6'</span>
|
||
<span class="gp">>>> </span><span class="n">find_library</span><span class="p">(</span><span class="s2">"bz2"</span><span class="p">)</span>
|
||
<span class="go">'libbz2.so.1.0'</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-342">On OS X, <code class="xref py py-func docutils literal"><span class="pre">find_library()</span></code> tries several predefined naming schemes and paths to locate the library, and returns a full pathname if successful:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes.util</span> <span class="k">import</span> <span class="n">find_library</span>
|
||
<span class="gp">>>> </span><span class="n">find_library</span><span class="p">(</span><span class="s2">"c"</span><span class="p">)</span>
|
||
<span class="go">'/usr/lib/libc.dylib'</span>
|
||
<span class="gp">>>> </span><span class="n">find_library</span><span class="p">(</span><span class="s2">"m"</span><span class="p">)</span>
|
||
<span class="go">'/usr/lib/libm.dylib'</span>
|
||
<span class="gp">>>> </span><span class="n">find_library</span><span class="p">(</span><span class="s2">"bz2"</span><span class="p">)</span>
|
||
<span class="go">'/usr/lib/libbz2.dylib'</span>
|
||
<span class="gp">>>> </span><span class="n">find_library</span><span class="p">(</span><span class="s2">"AGL"</span><span class="p">)</span>
|
||
<span class="go">'/System/Library/Frameworks/AGL.framework/AGL'</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-343">On Windows, <code class="xref py py-func docutils literal"><span class="pre">find_library()</span></code> searches along the system search path, and returns the full pathname, but since there is no predefined naming scheme a call like <code class="docutils literal"><span class="pre">find_library("c")</span></code> will fail and return <code class="docutils literal"><span class="pre">None</span></code>.</span></p><p><span class="yiyi-st" id="yiyi-344">If wrapping a shared library with <a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>, it <em>may</em> be better to determine the shared library name at development time, and hardcode that into the wrapper module instead of using <code class="xref py py-func docutils literal"><span class="pre">find_library()</span></code> to locate the library at runtime.</span></p></div><div class="section" id="loading-shared-libraries"><h3><span class="yiyi-st" id="yiyi-345">16.16.2.2. </span><span class="yiyi-st" id="yiyi-346">加载共享库</span></h3><p><span class="yiyi-st" id="yiyi-347">有几种方法可以将共享库加载到Python进程中。</span><span class="yiyi-st" id="yiyi-348">一种方法是实例化以下类之一:</span></p><dl class="class"><dt id="ctypes.CDLL"><span class="yiyi-st" id="yiyi-349"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">CDLL</code><span class="sig-paren">(</span><em>name</em>, <em>mode=DEFAULT_MODE</em>, <em>handle=None</em>, <em>use_errno=False</em>, <em>use_last_error=False</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-350">这个类的实例代表加载的共享库。</span><span class="yiyi-st" id="yiyi-351">这些库中的函数使用标准的C调用约定,并假定返回<code class="xref c c-type docutils literal"><span class="pre">int</span></code>。</span></p></dd></dl><dl class="class"><dt id="ctypes.OleDLL"><span class="yiyi-st" id="yiyi-352"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">OleDLL</code><span class="sig-paren">(</span><em>name</em>, <em>mode=DEFAULT_MODE</em>, <em>handle=None</em>, <em>use_errno=False</em>, <em>use_last_error=False</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-353">仅限Windows:此类的实例表示已加载的共享库,这些库中的函数使用<code class="docutils literal"><span class="pre">stdcall</span></code>调用约定,并假定返回特定于窗口的<a class="reference internal" href="#ctypes.HRESULT" title="ctypes.HRESULT"><code class="xref py py-class docutils literal"><span class="pre">HRESULT</span></code></a>代码。</span><span class="yiyi-st" id="yiyi-354"><a class="reference internal" href="#ctypes.HRESULT" title="ctypes.HRESULT"><code class="xref py py-class docutils literal"><span class="pre">HRESULT</span></code></a> values contain information specifying whether the function call failed or succeeded, together with additional error code. </span><span class="yiyi-st" id="yiyi-355">如果返回值表示失败,则会自动产生<a class="reference internal" href="exceptions.html#OSError" title="OSError"><code class="xref py py-class docutils literal"><span class="pre">OSError</span></code></a>。</span></p><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-356"><span class="versionmodified">在版本3.3中更改:</span> <a class="reference internal" href="exceptions.html#WindowsError" title="WindowsError"><code class="xref py py-exc docutils literal"><span class="pre">WindowsError</span></code></a>曾被提及。</span></p></div></dd></dl><dl class="class"><dt id="ctypes.WinDLL"><span class="yiyi-st" id="yiyi-357"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">WinDLL</code><span class="sig-paren">(</span><em>name</em>, <em>mode=DEFAULT_MODE</em>, <em>handle=None</em>, <em>use_errno=False</em>, <em>use_last_error=False</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-358">仅Windows:此类的实例表示已加载的共享库,这些库中的函数使用<code class="docutils literal"><span class="pre">stdcall</span></code>调用约定,并且默认情况下会假定返回<code class="xref c c-type docutils literal"><span class="pre">int</span></code>。</span></p><p><span class="yiyi-st" id="yiyi-359">在Windows CE上,只使用标准调用约定,为了方便,<a class="reference internal" href="#ctypes.WinDLL" title="ctypes.WinDLL"><code class="xref py py-class docutils literal"><span class="pre">WinDLL</span></code></a>和<a class="reference internal" href="#ctypes.OleDLL" title="ctypes.OleDLL"><code class="xref py py-class docutils literal"><span class="pre">OleDLL</span></code></a>在此平台上使用标准调用约定。</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-360">在调用这些库导出的任何函数之前释放Python <a class="reference internal" href="../glossary.html#term-global-interpreter-lock"><span class="xref std std-term">global interpreter lock</span></a>,然后重新获取。</span></p><dl class="class"><dt id="ctypes.PyDLL"><span class="yiyi-st" id="yiyi-361"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">PyDLL</code><span class="sig-paren">(</span><em>name</em>, <em>mode=DEFAULT_MODE</em>, <em>handle=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-362">Instances of this class behave like <a class="reference internal" href="#ctypes.CDLL" title="ctypes.CDLL"><code class="xref py py-class docutils literal"><span class="pre">CDLL</span></code></a> instances, except that the Python GIL is <em>not</em> released during the function call, and after the function execution the Python error flag is checked. </span><span class="yiyi-st" id="yiyi-363">如果设置了错误标志,则会引发Python异常。</span></p><p><span class="yiyi-st" id="yiyi-364">因此,这仅用于直接调用Python C api函数。</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-365">所有这些类都可以通过调用至少一个参数(共享库的路径名)来实例化。</span><span class="yiyi-st" id="yiyi-366">如果您已经有一个已经加载的共享库的句柄,它可以作为<code class="docutils literal"><span class="pre">handle</span></code>命名参数传递,否则底层平台<code class="docutils literal"><span class="pre">dlopen</span></code>或<code class="docutils literal"><span class="pre">LoadLibrary函数用于将库加载到进程中,并获取它的句柄。</span></code></span></p><p><span class="yiyi-st" id="yiyi-367"><em>mode</em>参数可用于指定库的加载方式。</span><span class="yiyi-st" id="yiyi-368">有关详细信息,请参阅Windows上的<em class="manpage">dlopen(3)</em>联机帮助页,<em>mode</em>将被忽略。</span></p><p><span class="yiyi-st" id="yiyi-369"><em>use_errno</em>参数设置为True时,将启用一个ctypes机制,以允许以安全的方式访问系统<a class="reference internal" href="errno.html#module-errno" title="errno: Standard errno system symbols."><code class="xref py py-data docutils literal"><span class="pre">errno</span></code></a>错误编号。</span><span class="yiyi-st" id="yiyi-370"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a> maintains a thread-local copy of the systems <a class="reference internal" href="errno.html#module-errno" title="errno: Standard errno system symbols."><code class="xref py py-data docutils literal"><span class="pre">errno</span></code></a> variable; if you call foreign functions created with <code class="docutils literal"><span class="pre">use_errno=True</span></code> then the <a class="reference internal" href="errno.html#module-errno" title="errno: Standard errno system symbols."><code class="xref py py-data docutils literal"><span class="pre">errno</span></code></a> value before the function call is swapped with the ctypes private copy, the same happens immediately after the function call.</span></p><p><span class="yiyi-st" id="yiyi-371">函数<a class="reference internal" href="#ctypes.get_errno" title="ctypes.get_errno"><code class="xref py py-func docutils literal"><span class="pre">ctypes.get_errno()</span></code></a>返回ctypes专用副本的值,函数<a class="reference internal" href="#ctypes.set_errno" title="ctypes.set_errno"><code class="xref py py-func docutils literal"><span class="pre">ctypes.set_errno()</span></code></a>将ctypes专用副本更改为新值并返回前值。</span></p><p><span class="yiyi-st" id="yiyi-372">The <em>use_last_error</em> parameter, when set to True, enables the same mechanism for the Windows error code which is managed by the <a class="reference internal" href="#ctypes.GetLastError" title="ctypes.GetLastError"><code class="xref py py-func docutils literal"><span class="pre">GetLastError()</span></code></a> and <code class="xref py py-func docutils literal"><span class="pre">SetLastError()</span></code> Windows API functions; <a class="reference internal" href="#ctypes.get_last_error" title="ctypes.get_last_error"><code class="xref py py-func docutils literal"><span class="pre">ctypes.get_last_error()</span></code></a> and <a class="reference internal" href="#ctypes.set_last_error" title="ctypes.set_last_error"><code class="xref py py-func docutils literal"><span class="pre">ctypes.set_last_error()</span></code></a> are used to request and change the ctypes private copy of the windows error code.</span></p><dl class="data"><dt><span class="yiyi-st" id="yiyi-373"> <code class="descclassname">ctypes.</code><code class="descname">RTLD_GLOBAL</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-374">标记用作<em>模式</em>参数。</span><span class="yiyi-st" id="yiyi-375">在该标志不可用的平台上,它被定义为整数零。</span></p></dd></dl><dl class="data"><dt><span class="yiyi-st" id="yiyi-376"> <code class="descclassname">ctypes.</code><code class="descname">RTLD_LOCAL</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-377">标记用作<em>模式</em>参数。</span><span class="yiyi-st" id="yiyi-378">在不可用的平台上,它与<em>RTLD_GLOBAL</em>相同。</span></p></dd></dl><dl class="data"><dt><span class="yiyi-st" id="yiyi-379"> <code class="descclassname">ctypes.</code><code class="descname">DEFAULT_MODE</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-380">用于加载共享库的默认模式。</span><span class="yiyi-st" id="yiyi-381">在OSX 10.3上,这是<em>RTLD_GLOBAL</em>,否则它与<em>RTLD_LOCAL</em>相同。</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-382">这些类的实例没有公共方法。</span><span class="yiyi-st" id="yiyi-383">共享库导出的函数可以作为属性或索引进行访问。</span><span class="yiyi-st" id="yiyi-384">请注意,通过属性访问函数会缓存结果,因此每次重复访问它都会返回相同的对象。</span><span class="yiyi-st" id="yiyi-385">另一方面,通过索引访问它每次都会返回一个新对象:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">libc</span><span class="o">.</span><span class="n">time</span> <span class="o">==</span> <span class="n">libc</span><span class="o">.</span><span class="n">time</span>
|
||
<span class="go">True</span>
|
||
<span class="gp">>>> </span><span class="n">libc</span><span class="p">[</span><span class="s1">'time'</span><span class="p">]</span> <span class="o">==</span> <span class="n">libc</span><span class="p">[</span><span class="s1">'time'</span><span class="p">]</span>
|
||
<span class="go">False</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-386">以下公共属性可用,它们的名称以下划线开头,不与导出的函数名称冲突:</span></p><dl class="attribute"><dt id="ctypes.PyDLL._handle"><span class="yiyi-st" id="yiyi-387"> <code class="descclassname">PyDLL.</code><code class="descname">_handle</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-388">用于访问库的系统句柄。</span></p></dd></dl><dl class="attribute"><dt id="ctypes.PyDLL._name"><span class="yiyi-st" id="yiyi-389"> <code class="descclassname">PyDLL.</code><code class="descname">_name</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-390">在构造函数中传递的库的名称。</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-391">共享库也可以通过使用作为<a class="reference internal" href="#ctypes.LibraryLoader" title="ctypes.LibraryLoader"><code class="xref py py-class docutils literal"><span class="pre">LibraryLoader</span></code></a>类的实例的预制对象之一加载,或者通过调用<code class="xref py py-meth docutils literal"><span class="pre">LoadLibrary()</span></code>方法或通过检索库作为加载器实例的属性。</span></p><dl class="class"><dt id="ctypes.LibraryLoader"><span class="yiyi-st" id="yiyi-392"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">LibraryLoader</code><span class="sig-paren">(</span><em>dlltype</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-393">加载共享库的类。</span><span class="yiyi-st" id="yiyi-394"><em>dlltype</em>应该是<a class="reference internal" href="#ctypes.CDLL" title="ctypes.CDLL"><code class="xref py py-class docutils literal"><span class="pre">CDLL</span></code></a>,<a class="reference internal" href="#ctypes.PyDLL" title="ctypes.PyDLL"><code class="xref py py-class docutils literal"><span class="pre">PyDLL</span></code></a>,<a class="reference internal" href="#ctypes.WinDLL" title="ctypes.WinDLL"><code class="xref py py-class docutils literal"><span class="pre">WinDLL</span></code></a>或<a class="reference internal" href="#ctypes.OleDLL" title="ctypes.OleDLL"><code class="xref py py-class docutils literal"><span class="pre">OleDLL</span></code></a>类型之一。</span></p><p><span class="yiyi-st" id="yiyi-395"><a class="reference internal" href="../reference/datamodel.html#object.__getattr__" title="object.__getattr__"><code class="xref py py-meth docutils literal"><span class="pre">__getattr__()</span></code></a>具有特殊的行为:它允许通过访问共享库作为库加载器实例的属性来加载共享库。</span><span class="yiyi-st" id="yiyi-396">结果被缓存,所以重复的属性访问每次返回相同的库。</span></p><dl class="method"><dt id="ctypes.LibraryLoader.LoadLibrary"><span class="yiyi-st" id="yiyi-397"> <code class="descname">LoadLibrary</code><span class="sig-paren">(</span><em>name</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-398">将共享库加载到进程中并返回。</span><span class="yiyi-st" id="yiyi-399">此方法始终返回库的新实例。</span></p></dd></dl></dd></dl><p><span class="yiyi-st" id="yiyi-400">下面的预制库加载器可以利用:</span></p><dl class="data"><dt><span class="yiyi-st" id="yiyi-401"> <code class="descclassname">ctypes.</code><code class="descname">cdll</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-402">创建<a class="reference internal" href="#ctypes.CDLL" title="ctypes.CDLL"><code class="xref py py-class docutils literal"><span class="pre">CDLL</span></code></a>实例。</span></p></dd></dl><dl class="data"><dt><span class="yiyi-st" id="yiyi-403"> <code class="descclassname">ctypes.</code><code class="descname">windll</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-404">仅限Windows:创建<a class="reference internal" href="#ctypes.WinDLL" title="ctypes.WinDLL"><code class="xref py py-class docutils literal"><span class="pre">WinDLL</span></code></a>实例。</span></p></dd></dl><dl class="data"><dt><span class="yiyi-st" id="yiyi-405"> <code class="descclassname">ctypes.</code><code class="descname">oledll</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-406">仅限Windows:创建<a class="reference internal" href="#ctypes.OleDLL" title="ctypes.OleDLL"><code class="xref py py-class docutils literal"><span class="pre">OleDLL</span></code></a>实例。</span></p></dd></dl><dl class="data"><dt><span class="yiyi-st" id="yiyi-407"> <code class="descclassname">ctypes.</code><code class="descname">pydll</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-408">创建<a class="reference internal" href="#ctypes.PyDLL" title="ctypes.PyDLL"><code class="xref py py-class docutils literal"><span class="pre">PyDLL</span></code></a>实例。</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-409">为了直接访问C Python api,可以使用一个随时可用的Python共享库对象:</span></p><dl class="data"><dt><span class="yiyi-st" id="yiyi-410"> <code class="descclassname">ctypes.</code><code class="descname">pythonapi</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-411">一个<a class="reference internal" href="#ctypes.PyDLL" title="ctypes.PyDLL"><code class="xref py py-class docutils literal"><span class="pre">PyDLL</span></code></a>实例,它将Python C API函数公开为属性。</span><span class="yiyi-st" id="yiyi-412">请注意,所有这些函数都假定返回C <code class="xref c c-type docutils literal"><span class="pre">int</span></code>,这当然不总是事实,所以您必须分配正确的<code class="xref py py-attr docutils literal"><span class="pre">restype</span></code>属性来使用这些函数。</span></p></dd></dl></div><div class="section" id="foreign-functions"><h3><span class="yiyi-st" id="yiyi-413">16.16.2.3. </span><span class="yiyi-st" id="yiyi-414">外部函数</span></h3><p><span class="yiyi-st" id="yiyi-415">如前一节所述,外部函数可以作为加载共享库的属性来访问。</span><span class="yiyi-st" id="yiyi-416">默认以这种方式创建的函数对象接受任意数量的参数,接受任何ctypes数据实例作为参数,并返回由库加载器指定的默认结果类型。</span><span class="yiyi-st" id="yiyi-417">他们是一个私人课堂的例子:</span></p><dl class="class"><dt id="ctypes._FuncPtr"><span class="yiyi-st" id="yiyi-418"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">_FuncPtr</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-419">C可调用外部函数的基类。</span></p><p><span class="yiyi-st" id="yiyi-420">外部函数的实例也是C兼容的数据类型;它们代表C函数指针。</span></p><p><span class="yiyi-st" id="yiyi-421">这种行为可以通过分配给外部函数对象的特殊属性来定制。</span></p><dl class="attribute"><dt id="ctypes._FuncPtr.restype"><span class="yiyi-st" id="yiyi-422"> <code class="descname">restype</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-423">指定一个ctypes类型来指定外部函数的结果类型。</span><span class="yiyi-st" id="yiyi-424">对<code class="xref c c-type docutils literal"><span class="pre">void</span></code>使用<code class="docutils literal"><span class="pre">None</span></code>,该函数不返回任何内容。</span></p><p><span class="yiyi-st" id="yiyi-425">可以分配一个不是ctypes类型的可调用Python对象,在这种情况下,该函数被假定为返回一个C <code class="xref c c-type docutils literal"><span class="pre">int</span></code>,并且可调用对象将被调用该整数,从而允许进一步处理或错误检查。</span><span class="yiyi-st" id="yiyi-426">不推荐使用这种方式,为了更灵活的后处理或错误检查,请使用ctypes数据类型作为<a class="reference internal" href="#ctypes._FuncPtr.restype" title="ctypes._FuncPtr.restype"><code class="xref py py-attr docutils literal"><span class="pre">restype</span></code></a>,并为<a class="reference internal" href="#ctypes._FuncPtr.errcheck" title="ctypes._FuncPtr.errcheck"><code class="xref py py-attr docutils literal"><span class="pre">errcheck</span></code></a>属性指定一个可调用对象。</span></p></dd></dl><dl class="attribute"><dt id="ctypes._FuncPtr.argtypes"><span class="yiyi-st" id="yiyi-427"> <code class="descname">argtypes</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-428">分配一个ctypes类型的元组来指定该函数接受的参数类型。</span><span class="yiyi-st" id="yiyi-429">使用<code class="docutils literal"><span class="pre">stdcall</span></code>调用约定的函数只能使用与该元组的长度相同数量的参数进行调用;使用C调用约定的函数也接受附加的、未指定的参数。</span></p><p><span class="yiyi-st" id="yiyi-430">当调用外部函数时,每个实际参数都会传递给<a class="reference internal" href="#ctypes._FuncPtr.argtypes" title="ctypes._FuncPtr.argtypes"><code class="xref py py-attr docutils literal"><span class="pre">argtypes</span></code></a>元组中项目的<code class="xref py py-meth docutils literal"><span class="pre">from_param()</span></code>类方法,该方法允许将实际参数调整为该外部函数接受的对象。</span><span class="yiyi-st" id="yiyi-431">例如,<a class="reference internal" href="#ctypes._FuncPtr.argtypes" title="ctypes._FuncPtr.argtypes"><code class="xref py py-attr docutils literal"><span class="pre">argtypes</span></code></a>元组中的<a class="reference internal" href="#ctypes.c_char_p" title="ctypes.c_char_p"><code class="xref py py-class docutils literal"><span class="pre">c_char_p</span></code></a>项将使用ctypes转换规则将作为参数传递的字符串转换为字节对象。</span></p><p><span class="yiyi-st" id="yiyi-432">新增功能:现在可以将项目放入非ctypes类型的argtypes中,但每个项目必须有一个返回可用作参数(整数,字符串,ctypes实例)的值的<code class="xref py py-meth docutils literal"><span class="pre">from_param()</span></code>方法。</span><span class="yiyi-st" id="yiyi-433">这允许定义可以将自定义对象作为函数参数的适配器。</span></p></dd></dl><dl class="attribute"><dt id="ctypes._FuncPtr.errcheck"><span class="yiyi-st" id="yiyi-434"> <code class="descname">errcheck</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-435">为此属性分配一个Python函数或另一个可调用对象。</span><span class="yiyi-st" id="yiyi-436">可调用函数将被调用三个或更多参数:</span></p><dl class="function"><dt><span class="yiyi-st" id="yiyi-437"> <code class="descname">callable</code><span class="sig-paren">(</span><em>result</em>, <em>func</em>, <em>arguments</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-438"><em>结果</em>是外部函数返回的结果,由<a class="reference internal" href="#ctypes._FuncPtr.restype" title="ctypes._FuncPtr.restype"><code class="xref py py-attr docutils literal"><span class="pre">restype</span></code></a>属性指定。</span></p><p><span class="yiyi-st" id="yiyi-439"><em>func</em>是外部函数对象本身,这允许重用相同的可调用对象来检查或后处理几个函数的结果。</span></p><p><span class="yiyi-st" id="yiyi-440"><em>arguments</em>是一个包含最初传递给函数调用的参数的元组,这允许专门化所使用参数的行为。</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-441">该函数返回的对象将从外部函数调用中返回,但它也可以检查结果值并在外部函数调用失败时引发异常。</span></p></dd></dl></dd></dl><dl class="exception"><dt id="ctypes.ArgumentError"><span class="yiyi-st" id="yiyi-442"> <em class="property">exception </em><code class="descclassname">ctypes.</code><code class="descname">ArgumentError</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-443">当外部函数调用不能转换传递的参数之一时引发此异常。</span></p></dd></dl></div><div class="section" id="function-prototypes"><h3><span class="yiyi-st" id="yiyi-444">16.16.2.4. </span><span class="yiyi-st" id="yiyi-445">函数原型</span></h3><p><span class="yiyi-st" id="yiyi-446">外部函数也可以通过实例化函数原型来创建。</span><span class="yiyi-st" id="yiyi-447">函数原型与C中的函数原型相似;他们描述了一个函数(返回类型,参数类型,调用约定),而没有定义实现。</span><span class="yiyi-st" id="yiyi-448">必须使用所需的结果类型和函数的参数类型来调用工厂函数。</span></p><dl class="function"><dt id="ctypes.CFUNCTYPE"><span class="yiyi-st" id="yiyi-449"> <code class="descclassname">ctypes.</code><code class="descname">CFUNCTYPE</code><span class="sig-paren">(</span><em>restype</em>, <em>*argtypes</em>, <em>use_errno=False</em>, <em>use_last_error=False</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-450">返回的函数原型创建使用标准C调用约定的函数。</span><span class="yiyi-st" id="yiyi-451">该功能将在通话过程中释放GIL。</span><span class="yiyi-st" id="yiyi-452">If <em>use_errno</em> is set to True, the ctypes private copy of the system <a class="reference internal" href="errno.html#module-errno" title="errno: Standard errno system symbols."><code class="xref py py-data docutils literal"><span class="pre">errno</span></code></a> variable is exchanged with the real <a class="reference internal" href="errno.html#module-errno" title="errno: Standard errno system symbols."><code class="xref py py-data docutils literal"><span class="pre">errno</span></code></a> value before and after the call; <em>use_last_error</em> does the same for the Windows error code.</span></p></dd></dl><dl class="function"><dt id="ctypes.WINFUNCTYPE"><span class="yiyi-st" id="yiyi-453"> <code class="descclassname">ctypes.</code><code class="descname">WINFUNCTYPE</code><span class="sig-paren">(</span><em>restype</em>, <em>*argtypes</em>, <em>use_errno=False</em>, <em>use_last_error=False</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-454">仅Windows:返回的函数原型创建使用<code class="docutils literal"><span class="pre">stdcall</span></code>调用约定的函数,除了在Windows CE上,<a class="reference internal" href="#ctypes.WINFUNCTYPE" title="ctypes.WINFUNCTYPE"><code class="xref py py-func docutils literal"><span class="pre">WINFUNCTYPE()</span></code></a>与<a class="reference internal" href="#ctypes.CFUNCTYPE" title="ctypes.CFUNCTYPE"><code class="xref py py-func docutils literal"><span class="pre">CFUNCTYPE()</span></code></a></span><span class="yiyi-st" id="yiyi-455">该功能将在通话过程中释放GIL。</span><span class="yiyi-st" id="yiyi-456"><em>use_errno</em>和<em>use_last_error</em>具有与上述相同的含义。</span></p></dd></dl><dl class="function"><dt id="ctypes.PYFUNCTYPE"><span class="yiyi-st" id="yiyi-457"> <code class="descclassname">ctypes.</code><code class="descname">PYFUNCTYPE</code><span class="sig-paren">(</span><em>restype</em>, <em>*argtypes</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-458">返回的函数原型创建使用Python调用约定的函数。</span><span class="yiyi-st" id="yiyi-459">在通话过程中,<em>功能不会</em>释放GIL。</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-460">这些工厂函数创建的函数原型可以以不同的方式实例化,具体取决于调用中参数的类型和数量:</span></p><span class="yiyi-st" id="yiyi-474"> <blockquote><div><dl class="function"><dt><code class="descname">prototype</code><span class="sig-paren">(</span><em>address</em><span class="sig-paren">)</span></dt> <dd><p>在指定的地址(address)返回外部函数,返回类型为整形</p></dd></dl> <dl class="function"><dt><code class="descname">prototype</code><span class="sig-paren">(</span><em>callable</em><span class="sig-paren">)</span></dt> <dd><p>Create a C callable function (a callback function) from a Python <em>callable</em>.</p></dd></dl> <dl class="function"><dt><code class="descname">prototype</code><span class="sig-paren">(</span><em>func_spec</em><span class="optional">[</span>, <em>paramflags</em><span class="optional">]</span><span class="sig-paren">)</span></dt> <dd><p>Returns a foreign function exported by a shared library. <em>func_spec</em> must be a 2-tuple <code class="docutils literal"><span class="pre">(name_or_ordinal,</span> <span class="pre">library)</span></code>. The first item is the name of the exported function as string, or the ordinal of the exported function as small integer. The second item is the shared library instance.</p></dd></dl> <dl class="function"><dt><code class="descname">prototype</code><span class="sig-paren">(</span><em>vtbl_index</em>, <em>name</em><span class="optional">[</span>, <em>paramflags</em><span class="optional">[</span>, <em>iid</em><span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span></dt> <dd><p>Returns a foreign function that will call a COM method. <em>vtbl_index</em> is the index into the virtual function table, a small non-negative integer. <em>name</em> is name of the COM method. <em>iid</em> is an optional pointer to the interface identifier which is used in extended error reporting.</p> <p>COM methods use a special calling convention: They require a pointer to the COM interface as first argument, in addition to those parameters that are specified in the <code class="xref py py-attr docutils literal"><span class="pre">argtypes</span></code> tuple.</p></dd></dl> <p>The optional <em>paramflags</em> parameter creates foreign function wrappers with much more functionality than the features described above.</p> <p><em>paramflags</em> must be a tuple of the same length as <code class="xref py py-attr docutils literal"><span class="pre">argtypes</span></code>.</p> <p>Each item in this tuple contains further information about a parameter, it must be a tuple containing one, two, or three items.</p> <p>The first item is an integer containing a combination of direction flags for the parameter:</p> <blockquote><div><dl class="docutils"><dt>1</dt> <dd>Specifies an input parameter to the function.</dd> <dt>2</dt> <dd>Output parameter. The foreign function fills in a value.</dd> <dt>4</dt> <dd>Input parameter which defaults to the integer zero.</dd></dl></div></blockquote> <p>The optional second item is the parameter name as string. If this is specified, the foreign function can be called with named parameters.</p> <p>The optional third item is the default value for this parameter.</p></div></blockquote></span><p><span class="yiyi-st" id="yiyi-461">此示例演示如何包装Windows <code class="docutils literal"><span class="pre">MessageBoxA</span></code>函数,以便它支持默认参数和命名参数。</span><span class="yiyi-st" id="yiyi-462">从Windows头文件的C声明是这样的:</span></p><pre><code class="language-python"><span></span><span class="n">WINUSERAPI</span> <span class="nb">int</span> <span class="n">WINAPI</span>
|
||
<span class="n">MessageBoxA</span><span class="p">(</span>
|
||
<span class="n">HWND</span> <span class="n">hWnd</span><span class="p">,</span>
|
||
<span class="n">LPCSTR</span> <span class="n">lpText</span><span class="p">,</span>
|
||
<span class="n">LPCSTR</span> <span class="n">lpCaption</span><span class="p">,</span>
|
||
<span class="n">UINT</span> <span class="n">uType</span><span class="p">);</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-463">这是用<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>打包的:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes</span> <span class="k">import</span> <span class="n">c_int</span><span class="p">,</span> <span class="n">WINFUNCTYPE</span><span class="p">,</span> <span class="n">windll</span>
|
||
<span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes.wintypes</span> <span class="k">import</span> <span class="n">HWND</span><span class="p">,</span> <span class="n">LPCSTR</span><span class="p">,</span> <span class="n">UINT</span>
|
||
<span class="gp">>>> </span><span class="n">prototype</span> <span class="o">=</span> <span class="n">WINFUNCTYPE</span><span class="p">(</span><span class="n">c_int</span><span class="p">,</span> <span class="n">HWND</span><span class="p">,</span> <span class="n">LPCSTR</span><span class="p">,</span> <span class="n">LPCSTR</span><span class="p">,</span> <span class="n">UINT</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">paramflags</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s2">"hwnd"</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s2">"text"</span><span class="p">,</span> <span class="s2">"Hi"</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s2">"caption"</span><span class="p">,</span> <span class="kc">None</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s2">"flags"</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">MessageBox</span> <span class="o">=</span> <span class="n">prototype</span><span class="p">((</span><span class="s2">"MessageBoxA"</span><span class="p">,</span> <span class="n">windll</span><span class="o">.</span><span class="n">user32</span><span class="p">),</span> <span class="n">paramflags</span><span class="p">)</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-464">现在可以通过以下方式调用MessageBox外部函数:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="n">MessageBox</span><span class="p">()</span>
|
||
<span class="gp">>>> </span><span class="n">MessageBox</span><span class="p">(</span><span class="n">text</span><span class="o">=</span><span class="s2">"Spam, spam, spam"</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">MessageBox</span><span class="p">(</span><span class="n">flags</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="s2">"foo bar"</span><span class="p">)</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-465">第二个示例演示输出参数。</span><span class="yiyi-st" id="yiyi-466">win32 <code class="docutils literal"><span class="pre">GetWindowRect</span></code>函数通过将指定窗口的维复制到调用者必须提供的<code class="docutils literal"><span class="pre">RECT</span></code>结构中来检索维。</span><span class="yiyi-st" id="yiyi-467">这是C声明:</span></p><pre><code class="language-python"><span></span><span class="n">WINUSERAPI</span> <span class="n">BOOL</span> <span class="n">WINAPI</span>
|
||
<span class="n">GetWindowRect</span><span class="p">(</span>
|
||
<span class="n">HWND</span> <span class="n">hWnd</span><span class="p">,</span>
|
||
<span class="n">LPRECT</span> <span class="n">lpRect</span><span class="p">);</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-468">这是用<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>打包的:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes</span> <span class="k">import</span> <span class="n">POINTER</span><span class="p">,</span> <span class="n">WINFUNCTYPE</span><span class="p">,</span> <span class="n">windll</span><span class="p">,</span> <span class="n">WinError</span>
|
||
<span class="gp">>>> </span><span class="kn">from</span> <span class="nn">ctypes.wintypes</span> <span class="k">import</span> <span class="n">BOOL</span><span class="p">,</span> <span class="n">HWND</span><span class="p">,</span> <span class="n">RECT</span>
|
||
<span class="gp">>>> </span><span class="n">prototype</span> <span class="o">=</span> <span class="n">WINFUNCTYPE</span><span class="p">(</span><span class="n">BOOL</span><span class="p">,</span> <span class="n">HWND</span><span class="p">,</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">RECT</span><span class="p">))</span>
|
||
<span class="gp">>>> </span><span class="n">paramflags</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s2">"hwnd"</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="s2">"lprect"</span><span class="p">)</span>
|
||
<span class="gp">>>> </span><span class="n">GetWindowRect</span> <span class="o">=</span> <span class="n">prototype</span><span class="p">((</span><span class="s2">"GetWindowRect"</span><span class="p">,</span> <span class="n">windll</span><span class="o">.</span><span class="n">user32</span><span class="p">),</span> <span class="n">paramflags</span><span class="p">)</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-469">带有输出参数的函数将自动返回输出参数值(如果有一个参数值),或者当有多个输出参数值时,包含输出参数值的元组将被自动返回,所以GetWindowRect函数现在会在调用时返回一个RECT实例。</span></p><p><span class="yiyi-st" id="yiyi-470">输出参数可以与<code class="xref py py-attr docutils literal"><span class="pre">errcheck</span></code>协议结合使用,以进行进一步的输出处理和错误检查。</span><span class="yiyi-st" id="yiyi-471">win32 <code class="docutils literal"><span class="pre">GetWindowRect</span></code> api函数返回一个<code class="docutils literal"><span class="pre">BOOL</span></code>来表示成功或失败,所以这个函数可以进行错误检查,并在api调用失败时引发异常:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="k">def</span> <span class="nf">errcheck</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">if</span> <span class="ow">not</span> <span class="n">result</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">raise</span> <span class="n">WinError</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="n">args</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">GetWindowRect</span><span class="o">.</span><span class="n">errcheck</span> <span class="o">=</span> <span class="n">errcheck</span>
|
||
<span class="go">>>></span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-472">如果<code class="xref py py-attr docutils literal"><span class="pre">errcheck</span></code>函数返回参数元组,它将保持不变,<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>将继续其在输出参数上执行的正常处理。</span><span class="yiyi-st" id="yiyi-473">If you want to return a tuple of window coordinates instead of a <code class="docutils literal"><span class="pre">RECT</span></code> instance, you can retrieve the fields in the function and return them instead, the normal processing will no longer take place:</span></p><pre><code class="language-python"><span></span><span class="gp">>>> </span><span class="k">def</span> <span class="nf">errcheck</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
|
||
<span class="gp">... </span> <span class="k">if</span> <span class="ow">not</span> <span class="n">result</span><span class="p">:</span>
|
||
<span class="gp">... </span> <span class="k">raise</span> <span class="n">WinError</span><span class="p">()</span>
|
||
<span class="gp">... </span> <span class="n">rc</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||
<span class="gp">... </span> <span class="k">return</span> <span class="n">rc</span><span class="o">.</span><span class="n">left</span><span class="p">,</span> <span class="n">rc</span><span class="o">.</span><span class="n">top</span><span class="p">,</span> <span class="n">rc</span><span class="o">.</span><span class="n">bottom</span><span class="p">,</span> <span class="n">rc</span><span class="o">.</span><span class="n">right</span>
|
||
<span class="gp">...</span>
|
||
<span class="gp">>>> </span><span class="n">GetWindowRect</span><span class="o">.</span><span class="n">errcheck</span> <span class="o">=</span> <span class="n">errcheck</span>
|
||
<span class="go">>>></span>
|
||
</code></pre></div><div class="section" id="utility-functions"><h3><span class="yiyi-st" id="yiyi-475">16.16.2.5. </span><span class="yiyi-st" id="yiyi-476">工具函数</span></h3><dl class="function"><dt id="ctypes.addressof"><span class="yiyi-st" id="yiyi-477"> <code class="descclassname">ctypes.</code><code class="descname">addressof</code><span class="sig-paren">(</span><em>obj</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-478">以整数形式返回内存缓冲区的地址。</span><span class="yiyi-st" id="yiyi-479"><em>obj</em>必须是一个ctypes类型的实例。</span></p></dd></dl><dl class="function"><dt id="ctypes.alignment"><span class="yiyi-st" id="yiyi-480"> <code class="descclassname">ctypes.</code><code class="descname">alignment</code><span class="sig-paren">(</span><em>obj_or_type</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-481">返回ctypes类型的对齐要求。</span><span class="yiyi-st" id="yiyi-482"><em>obj_or_type</em>必须是ctypes类型或实例。</span></p></dd></dl><dl class="function"><dt id="ctypes.byref"><span class="yiyi-st" id="yiyi-483"> <code class="descclassname">ctypes.</code><code class="descname">byref</code><span class="sig-paren">(</span><em>obj</em><span class="optional">[</span>, <em>offset</em><span class="optional">]</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-484">返回指向<em>obj</em>的轻量级指针,该指针必须是ctypes类型的实例。</span><span class="yiyi-st" id="yiyi-485"><em>偏移量</em>默认为零,并且必须是一个将被添加到内部指针值的整数。</span></p><p><span class="yiyi-st" id="yiyi-486"><code class="docutils literal"><span class="pre">byref(obj,</span> <span class="pre">offset)</span></code>对应于这个C代码:</span></p><pre><code class="language-python"><span></span><span class="p">(((</span><span class="n">char</span> <span class="o">*</span><span class="p">)</span><span class="o">&</span><span class="n">obj</span><span class="p">)</span> <span class="o">+</span> <span class="n">offset</span><span class="p">)</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-487">返回的对象只能用作外部函数调用参数。</span><span class="yiyi-st" id="yiyi-488">它的行为与<code class="docutils literal"><span class="pre">pointer(obj)</span></code>类似,但构造速度更快。</span></p></dd></dl><dl class="function"><dt id="ctypes.cast"><span class="yiyi-st" id="yiyi-489"> <code class="descclassname">ctypes.</code><code class="descname">cast</code><span class="sig-paren">(</span><em>obj</em>, <em>type</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-490">该函数与C中的cast操作符类似。它返回一个指向与<em>obj</em>相同的内存块的<em>type</em>新实例。</span><span class="yiyi-st" id="yiyi-491"><em>type</em>必须是指针类型,<em>obj</em>必须是可以解释为指针的对象。</span></p></dd></dl><dl class="function"><dt id="ctypes.create_string_buffer"><span class="yiyi-st" id="yiyi-492"> <code class="descclassname">ctypes.</code><code class="descname">create_string_buffer</code><span class="sig-paren">(</span><em>init_or_size</em>, <em>size=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-493">这个函数创建一个可变的字符缓冲区。</span><span class="yiyi-st" id="yiyi-494">返回的对象是<a class="reference internal" href="#ctypes.c_char" title="ctypes.c_char"><code class="xref py py-class docutils literal"><span class="pre">c_char</span></code></a>的ctypes数组。</span></p><p><span class="yiyi-st" id="yiyi-495"><em>init_or_size</em> must be an integer which specifies the size of the array, or a bytes object which will be used to initialize the array items.</span></p><p><span class="yiyi-st" id="yiyi-496">如果一个字节对象被指定为第一个参数,那么缓冲区会比其长度大一个项目,以便数组中的最后一个元素是一个NUL终止字符。</span><span class="yiyi-st" id="yiyi-497">一个整数可以作为第二个参数传递,它允许指定数组的大小,如果不应该使用字节的长度。</span></p></dd></dl><dl class="function"><dt id="ctypes.create_unicode_buffer"><span class="yiyi-st" id="yiyi-498"> <code class="descclassname">ctypes.</code><code class="descname">create_unicode_buffer</code><span class="sig-paren">(</span><em>init_or_size</em>, <em>size=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-499">这个函数创建一个可变的unicode字符缓冲区。</span><span class="yiyi-st" id="yiyi-500">返回的对象是<a class="reference internal" href="#ctypes.c_wchar" title="ctypes.c_wchar"><code class="xref py py-class docutils literal"><span class="pre">c_wchar</span></code></a>的ctypes数组。</span></p><p><span class="yiyi-st" id="yiyi-501"><em>init_or_size</em>必须是一个整数,它指定数组的大小,或一个将用于初始化数组项的字符串。</span></p><p><span class="yiyi-st" id="yiyi-502">如果一个字符串被指定为第一个参数,那么缓冲区会比字符串的长度大一个项目,以便数组中的最后一个元素是一个NUL终止字符。</span><span class="yiyi-st" id="yiyi-503">一个整数可以作为第二个参数传递,它允许指定数组的大小,如果不应该使用字符串的长度。</span></p></dd></dl><dl class="function"><dt id="ctypes.DllCanUnloadNow"><span class="yiyi-st" id="yiyi-504"> <code class="descclassname">ctypes.</code><code class="descname">DllCanUnloadNow</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-505">仅Windows:这个函数是一个钩子,它允许实现具有ctypes的进程内COM服务器。</span><span class="yiyi-st" id="yiyi-506">它是从DllCanUnloadNow函数调用的_ctypes扩展dll导出的。</span></p></dd></dl><dl class="function"><dt id="ctypes.DllGetClassObject"><span class="yiyi-st" id="yiyi-507"> <code class="descclassname">ctypes.</code><code class="descname">DllGetClassObject</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-508">仅Windows:这个函数是一个钩子,它允许实现具有ctypes的进程内COM服务器。</span><span class="yiyi-st" id="yiyi-509">它是从DllGetClassObject函数调用的<code class="docutils literal"><span class="pre">_ctypes</span></code>扩展名dll导出的。</span></p></dd></dl><dl class="function"><dt id="ctypes.util.find_library"><span class="yiyi-st" id="yiyi-510"> <code class="descclassname">ctypes.util.</code><code class="descname">find_library</code><span class="sig-paren">(</span><em>name</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-511">尝试找到一个库并返回一个路径名。</span><span class="yiyi-st" id="yiyi-512"><em>name</em>是没有任何前缀(如<code class="docutils literal"><span class="pre">lib</span></code>),库后缀<code class="docutils literal"><span class="pre">.so</span></code>,<code class="docutils literal"><span class="pre">.dylib</span></code>或版本号这是用于posix链接器选项<a class="reference internal" href="tarfile.html#cmdoption-l"><code class="xref std std-option docutils literal"><span class="pre">-l</span></code></a></span><span class="yiyi-st" id="yiyi-513">如果没有找到库,则返回<code class="docutils literal"><span class="pre">None</span></code>。</span></p><p><span class="yiyi-st" id="yiyi-514">确切的功能依赖于系统。</span></p></dd></dl><dl class="function"><dt id="ctypes.util.find_msvcrt"><span class="yiyi-st" id="yiyi-515"> <code class="descclassname">ctypes.util.</code><code class="descname">find_msvcrt</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-516">仅Windows:返回Python使用的VC运行时库的文件名,以及扩展模块。</span><span class="yiyi-st" id="yiyi-517">如果无法确定库的名称,则返回<code class="docutils literal"><span class="pre">None</span></code>。</span></p><p><span class="yiyi-st" id="yiyi-518">如果你需要释放内存,例如,由扩展模块通过调用<code class="docutils literal"><span class="pre">free(void</span> <span class="pre">*)</span></code>来分配内存,这很重要您在分配内存的同一个库中使用该函数。</span></p></dd></dl><dl class="function"><dt id="ctypes.FormatError"><span class="yiyi-st" id="yiyi-519"> <code class="descclassname">ctypes.</code><code class="descname">FormatError</code><span class="sig-paren">(</span><span class="optional">[</span><em>code</em><span class="optional">]</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-520">仅限Windows:返回错误代码<em>代码</em>的文本描述。</span><span class="yiyi-st" id="yiyi-521">如果未指定错误代码,则通过调用Windows API函数GetLastError来使用上一个错误代码。</span></p></dd></dl><dl class="function"><dt id="ctypes.GetLastError"><span class="yiyi-st" id="yiyi-522"> <code class="descclassname">ctypes.</code><code class="descname">GetLastError</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-523">仅Windows:返回调用线程中由Windows设置的最后一个错误代码。</span><span class="yiyi-st" id="yiyi-524">该函数直接调用Windows <cite>GetLastError()</cite>函数,它不会返回错误代码的ctypes-private副本。</span></p></dd></dl><dl class="function"><dt id="ctypes.get_errno"><span class="yiyi-st" id="yiyi-525"> <code class="descclassname">ctypes.</code><code class="descname">get_errno</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-526">在调用线程中返回系统<a class="reference internal" href="errno.html#module-errno" title="errno: Standard errno system symbols."><code class="xref py py-data docutils literal"><span class="pre">errno</span></code></a>变量的ctypes-private副本的当前值。</span></p></dd></dl><dl class="function"><dt id="ctypes.get_last_error"><span class="yiyi-st" id="yiyi-527"> <code class="descclassname">ctypes.</code><code class="descname">get_last_error</code><span class="sig-paren">(</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-528">仅Windows:在调用线程中返回系统<code class="xref py py-data docutils literal"><span class="pre">LastError</span></code>变量的ctypes-private副本的当前值。</span></p></dd></dl><dl class="function"><dt id="ctypes.memmove"><span class="yiyi-st" id="yiyi-529"> <code class="descclassname">ctypes.</code><code class="descname">memmove</code><span class="sig-paren">(</span><em>dst</em>, <em>src</em>, <em>count</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-530">与标准C memmove库函数相同:将<em>count</em>个字节从<em>src</em>复制到<em>dst</em>。</span><span class="yiyi-st" id="yiyi-531"><em>dst</em>和<em>src</em>必须是可以转换为指针的整数或ctypes实例。</span></p></dd></dl><dl class="function"><dt id="ctypes.memset"><span class="yiyi-st" id="yiyi-532"> <code class="descclassname">ctypes.</code><code class="descname">memset</code><span class="sig-paren">(</span><em>dst</em>, <em>c</em>, <em>count</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-533">与标准C memset库函数相同:使用值<em>c</em>的<em>count</em>字节填充地址<em>dst</em>处的存储器块。 <em>dst</em>必须是指定地址的整数,或ctypes实例。</span></p></dd></dl><dl class="function"><dt id="ctypes.POINTER"><span class="yiyi-st" id="yiyi-534"> <code class="descclassname">ctypes.</code><code class="descname">POINTER</code><span class="sig-paren">(</span><em>type</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-535">这个工厂函数创建并返回一个新的ctypes指针类型。</span><span class="yiyi-st" id="yiyi-536">指针类型被缓存并在内部重用,所以重复调用这个函数很便宜。</span><span class="yiyi-st" id="yiyi-537"><em>类型</em>必须是ctypes类型。</span></p></dd></dl><dl class="function"><dt id="ctypes.pointer"><span class="yiyi-st" id="yiyi-538"> <code class="descclassname">ctypes.</code><code class="descname">pointer</code><span class="sig-paren">(</span><em>obj</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-539">这个函数创建一个新的指针实例,指向<em>obj</em>。</span><span class="yiyi-st" id="yiyi-540">返回的对象是<code class="docutils literal"><span class="pre">POINTER(type(obj))</span></code>类型。</span></p><p><span class="yiyi-st" id="yiyi-541">注意:如果你只是想把对象的指针传递给外部函数调用,你应该使用<code class="docutils literal"><span class="pre">byref(obj)</span></code>,这个速度要快得多。</span></p></dd></dl><dl class="function"><dt id="ctypes.resize"><span class="yiyi-st" id="yiyi-542"> <code class="descclassname">ctypes.</code><code class="descname">resize</code><span class="sig-paren">(</span><em>obj</em>, <em>size</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-543">此函数调整<em>obj</em>的内部缓冲区,该缓冲区必须是ctypes类型的实例。</span><span class="yiyi-st" id="yiyi-544">如<code class="docutils literal"><span class="pre">sizeof(type(obj))</span></code>所示,不可能使缓冲区小于对象类型的本地大小,但可以放大缓冲区。</span></p></dd></dl><dl class="function"><dt id="ctypes.set_errno"><span class="yiyi-st" id="yiyi-545"> <code class="descclassname">ctypes.</code><code class="descname">set_errno</code><span class="sig-paren">(</span><em>value</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-546">将调用线程中system <a class="reference internal" href="errno.html#module-errno" title="errno: Standard errno system symbols."><code class="xref py py-data docutils literal"><span class="pre">errno</span></code></a>变量的ctypes-private副本的当前值设置为<em>值</em>并返回以前的值。</span></p></dd></dl><dl class="function"><dt id="ctypes.set_last_error"><span class="yiyi-st" id="yiyi-547"> <code class="descclassname">ctypes.</code><code class="descname">set_last_error</code><span class="sig-paren">(</span><em>value</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-548">仅Windows:将调用线程中系统<code class="xref py py-data docutils literal"><span class="pre">LastError</span></code>变量的ctypes-private副本的当前值设置为<em>值</em>并返回以前的值。</span></p></dd></dl><dl class="function"><dt id="ctypes.sizeof"><span class="yiyi-st" id="yiyi-549"> <code class="descclassname">ctypes.</code><code class="descname">sizeof</code><span class="sig-paren">(</span><em>obj_or_type</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-550">返回ctypes类型或实例内存缓冲区的大小(以字节为单位)。</span><span class="yiyi-st" id="yiyi-551">与C <code class="docutils literal"><span class="pre">sizeof</span></code>运算符相同。</span></p></dd></dl><dl class="function"><dt id="ctypes.string_at"><span class="yiyi-st" id="yiyi-552"> <code class="descclassname">ctypes.</code><code class="descname">string_at</code><span class="sig-paren">(</span><em>address</em>, <em>size=-1</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-553">此函数返回从内存地址<em>address</em>开始的C字符串作为字节对象。</span><span class="yiyi-st" id="yiyi-554">如果指定了大小,则将其用作大小,否则将假定该字符串为零终止。</span></p></dd></dl><dl class="function"><dt id="ctypes.WinError"><span class="yiyi-st" id="yiyi-555"> <code class="descclassname">ctypes.</code><code class="descname">WinError</code><span class="sig-paren">(</span><em>code=None</em>, <em>descr=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-556">仅Windows:这个函数可能是ctypes中命名最差的东西。</span><span class="yiyi-st" id="yiyi-557">它创建了一个OSError实例。</span><span class="yiyi-st" id="yiyi-558">如果未指定<em>code</em>,则调用<code class="docutils literal"><span class="pre">GetLastError</span></code>来确定错误代码。</span><span class="yiyi-st" id="yiyi-559">如果<em>descr</em>没有被指定, <a class="reference internal" href="#ctypes.FormatError" title="ctypes.FormatError"><code class="xref py py-func docutils literal"><span class="pre">FormatError()</span></code></a>被调用来获取错误(error)的文本描述。</span></p><div class="versionchanged"><p><span class="yiyi-st" id="yiyi-560"><span class="versionmodified">在版本3.3中更改:</span>曾经创建<a class="reference internal" href="exceptions.html#WindowsError" title="WindowsError"><code class="xref py py-exc docutils literal"><span class="pre">WindowsError</span></code></a>的实例。</span></p></div></dd></dl><dl class="function"><dt id="ctypes.wstring_at"><span class="yiyi-st" id="yiyi-561"> <code class="descclassname">ctypes.</code><code class="descname">wstring_at</code><span class="sig-paren">(</span><em>address</em>, <em>size=-1</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-562">该函数以字符串的形式返回从内存地址<em>地址</em>开始的宽字符串。</span><span class="yiyi-st" id="yiyi-563">如果指定了<em>size</em>,则将其用作字符串的字符数,否则将假定字符串为零终止。</span></p></dd></dl></div><div class="section" id="data-types"><h3><span class="yiyi-st" id="yiyi-564">16.16.2.6. </span><span class="yiyi-st" id="yiyi-565">数据类型</span></h3><dl class="class"><dt id="ctypes._CData"><span class="yiyi-st" id="yiyi-566"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">_CData</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-567">这个非公共类是所有ctypes数据类型的公共基类。</span><span class="yiyi-st" id="yiyi-568">除此之外,所有ctypes类型实例都包含一个保存C兼容数据的内存块;内存块的地址由<a class="reference internal" href="#ctypes.addressof" title="ctypes.addressof"><code class="xref py py-func docutils literal"><span class="pre">addressof()</span></code></a>辅助函数返回。</span><span class="yiyi-st" id="yiyi-569">另一个实例变量暴露为<a class="reference internal" href="#ctypes._CData._objects" title="ctypes._CData._objects"><code class="xref py py-attr docutils literal"><span class="pre">_objects</span></code></a>;这包含其他Python对象,在内存块包含指针的情况下需要保持活动状态。</span></p><p><span class="yiyi-st" id="yiyi-570">ctypes数据类型的通用方法,这些都是类方法(确切地说,它们是<a class="reference internal" href="../glossary.html#term-metaclass"><span class="xref std std-term">metaclass</span></a>的方法):</span></p><dl class="method"><dt id="ctypes._CData.from_buffer"><span class="yiyi-st" id="yiyi-571"> <code class="descname">from_buffer</code><span class="sig-paren">(</span><em>source</em><span class="optional">[</span>, <em>offset</em><span class="optional">]</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-572">此方法返回共享<em>source</em>对象的缓冲区的ctypes实例。</span><span class="yiyi-st" id="yiyi-573"><em>source</em>对象必须支持可写缓冲区接口。</span><span class="yiyi-st" id="yiyi-574">可选的<em>offset</em>参数以字节为单位指定源缓冲区的偏移量;默认值为零。</span><span class="yiyi-st" id="yiyi-575">如果源缓冲区不够大,则会引发<a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal"><span class="pre">ValueError</span></code></a>。</span></p></dd></dl><dl class="method"><dt id="ctypes._CData.from_buffer_copy"><span class="yiyi-st" id="yiyi-576"> <code class="descname">from_buffer_copy</code><span class="sig-paren">(</span><em>source</em><span class="optional">[</span>, <em>offset</em><span class="optional">]</span><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-577">此方法创建一个ctypes实例,从必须可读的<em>source</em>对象缓冲区中复制缓冲区。</span><span class="yiyi-st" id="yiyi-578">可选的<em>offset</em>参数以字节为单位指定源缓冲区的偏移量;默认值为零。</span><span class="yiyi-st" id="yiyi-579">如果源缓冲区不够大,则会引发<a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal"><span class="pre">ValueError</span></code></a>。</span></p></dd></dl><dl class="method"><dt id="ctypes._CData.from_address"><span class="yiyi-st" id="yiyi-580"> <code class="descname">from_address</code><span class="sig-paren">(</span><em>address</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-581">此方法使用由<em>address</em>指定的内存返回一个ctypes类型实例,该内存必须是一个整数。</span></p></dd></dl><dl class="method"><dt id="ctypes._CData.from_param"><span class="yiyi-st" id="yiyi-582"> <code class="descname">from_param</code><span class="sig-paren">(</span><em>obj</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-583">此方法将<em>obj</em>调整为ctypes类型。</span><span class="yiyi-st" id="yiyi-584">当类型出现在外部函数的<code class="xref py py-attr docutils literal"><span class="pre">argtypes</span></code>元组中时,它将与外部函数调用中使用的实际对象一起调用;它必须返回一个可以用作函数调用参数的对象。</span></p><p><span class="yiyi-st" id="yiyi-585">所有的ctypes数据类型都有这个classmethod的默认实现,通常返回<em>obj</em>,如果这是一个类型的实例。</span><span class="yiyi-st" id="yiyi-586">有些类型也接受其他对象。</span></p></dd></dl><dl class="method"><dt id="ctypes._CData.in_dll"><span class="yiyi-st" id="yiyi-587"> <code class="descname">in_dll</code><span class="sig-paren">(</span><em>library</em>, <em>name</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-588">此方法返回由共享库导出的ctypes类型实例。</span><span class="yiyi-st" id="yiyi-589"><em>name</em>是导出数据的符号的名称,<em>library</em>是加载的共享库。</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-590">ctypes数据类型的通用实例变量:</span></p><dl class="attribute"><dt id="ctypes._CData._b_base_"><span class="yiyi-st" id="yiyi-591"> <code class="descname">_b_base_</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-592">有时ctypes数据实例不拥有它们包含的内存块,而是共享基础对象的部分内存块。</span><span class="yiyi-st" id="yiyi-593"><a class="reference internal" href="#ctypes._CData._b_base_" title="ctypes._CData._b_base_"><code class="xref py py-attr docutils literal"><span class="pre">_b_base_</span></code></a>只读成员是拥有内存块的root ctypes对象。</span></p></dd></dl><dl class="attribute"><dt id="ctypes._CData._b_needsfree_"><span class="yiyi-st" id="yiyi-594"> <code class="descname">_b_needsfree_</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-595">此只读变量在ctypes数据实例已分配内存块本身时为true,否则为false。</span></p></dd></dl><dl class="attribute"><dt id="ctypes._CData._objects"><span class="yiyi-st" id="yiyi-596"> <code class="descname">_objects</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-597">该成员要么是<code class="docutils literal"><span class="pre">None</span></code>,要么是包含需要保持活动状态的Python对象的字典,以便内存块内容保持有效。</span><span class="yiyi-st" id="yiyi-598">该对象仅用于调试;永远不要修改这本词典的内容。</span></p></dd></dl></dd></dl></div><div class="section" id="ctypes-fundamental-data-types-2"><h3><span class="yiyi-st" id="yiyi-599">16.16.2.7. </span><span class="yiyi-st" id="yiyi-600">基本数据类型</span></h3><dl class="class"><dt id="ctypes._SimpleCData"><span class="yiyi-st" id="yiyi-601"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">_SimpleCData</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-602">这个非公共类是所有基本ctypes数据类型的基类。</span><span class="yiyi-st" id="yiyi-603">这里提到它是因为它包含基本ctypes数据类型的通用属性。</span><span class="yiyi-st" id="yiyi-604"><a class="reference internal" href="#ctypes._SimpleCData" title="ctypes._SimpleCData"><code class="xref py py-class docutils literal"><span class="pre">_SimpleCData</span></code></a>是<a class="reference internal" href="#ctypes._CData" title="ctypes._CData"><code class="xref py py-class docutils literal"><span class="pre">_CData</span></code></a>的子类,所以它继承了它们的方法和属性。</span><span class="yiyi-st" id="yiyi-605">现在可以对不包含指针的ctypes数据类型进行酸洗。</span></p><p><span class="yiyi-st" id="yiyi-606">实例具有单个属性:</span></p><dl class="attribute"><dt id="ctypes._SimpleCData.value"><span class="yiyi-st" id="yiyi-607"> <code class="descname">value</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-608">该属性包含实例的实际值。</span><span class="yiyi-st" id="yiyi-609">对于整数和指针类型,它是一个整数,对于字符类型,它是单字节字节对象或字符串,对于字符指针类型,它是一个Python字节对象或字符串。</span></p><p><span class="yiyi-st" id="yiyi-610">当从ctypes实例中检索<code class="docutils literal"><span class="pre">value</span></code>属性时,通常每次都会返回一个新对象。</span><span class="yiyi-st" id="yiyi-611"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a> does <em>not</em> implement original object return, always a new object is constructed. </span><span class="yiyi-st" id="yiyi-612">所有其他ctypes对象实例也是如此。</span></p></dd></dl></dd></dl><p><span class="yiyi-st" id="yiyi-613">基本数据类型作为外部函数调用结果返回时,或者例如通过检索结构体字段成员或数组项,将被透明地转换为本机Python类型。</span><span class="yiyi-st" id="yiyi-614">换句话说,如果外部函数有<a class="reference internal" href="#ctypes.c_char_p" title="ctypes.c_char_p"><code class="xref py py-class docutils literal"><span class="pre">c_char_p</span></code></a>的<code class="xref py py-attr docutils literal"><span class="pre">restype</span></code>,您将总是收到一个Python字节对象<em>,而不是</em> 一个 <a class="reference internal" href="#ctypes.c_char_p" title="ctypes.c_char_p"><code class="xref py py-class docutils literal"><span class="pre">c_char_p</span></code></a>实例。</span></p><p><span class="yiyi-st" id="yiyi-615">基本数据类型的子类<em>不会</em>继承此行为。</span><span class="yiyi-st" id="yiyi-616">因此,如果外部函数<code class="xref py py-attr docutils literal"><span class="pre">restype</span></code>是<a class="reference internal" href="#ctypes.c_void_p" title="ctypes.c_void_p"><code class="xref py py-class docutils literal"><span class="pre">c_void_p</span></code></a>的子类,那么您将从函数调用中接收此子类的实例。</span><span class="yiyi-st" id="yiyi-617">当然,您可以通过访问<code class="docutils literal"><span class="pre">value</span></code>属性来获取指针的值。</span></p><p><span class="yiyi-st" id="yiyi-618">这些是基本的ctypes数据类型:</span></p><dl class="class"><dt id="ctypes.c_byte"><span class="yiyi-st" id="yiyi-619"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_byte</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-620">表示C <code class="xref c c-type docutils literal"><span class="pre">有符号</span> <span class="pre">char</span></code>数据类型,并将该值解释为小整数。</span><span class="yiyi-st" id="yiyi-621">构造函数接受一个可选的整数初始值设定项;没有溢出检查完成。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_char"><span class="yiyi-st" id="yiyi-622"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_char</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-623">表示C <code class="xref c c-type docutils literal"><span class="pre">char</span></code>数据类型,并将该值解释为单个字符。</span><span class="yiyi-st" id="yiyi-624">构造函数接受一个可选的字符串初始值设定项,字符串的长度必须恰好为一个字符。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_char_p"><span class="yiyi-st" id="yiyi-625"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_char_p</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-626">当它指向以零结尾的字符串时,表示C <code class="xref c c-type docutils literal"><span class="pre">char</span> <span class="pre">*</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-627">对于也可能指向二进制数据的通用字符指针,必须使用<code class="docutils literal"><span class="pre">POINTER(c_char)</span></code>。</span><span class="yiyi-st" id="yiyi-628">该构造函数接受一个整数地址或一个字节对象。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_double"><span class="yiyi-st" id="yiyi-629"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_double</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-630">表示C <code class="xref c c-type docutils literal"><span class="pre">double</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-631">构造函数接受一个可选的浮点初始值设定项。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_longdouble"><span class="yiyi-st" id="yiyi-632"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_longdouble</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-633">表示C <code class="xref c c-type docutils literal"><span class="pre">long</span> <span class="pre">double</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-634">构造函数接受一个可选的浮点初始值设定项。</span><span class="yiyi-st" id="yiyi-635">在<code class="docutils literal"><span class="pre">sizeof(long</span> <span class="pre">double)</span> <span class="pre">==</span> <span class="pre">sizeof(double)</span></code>是<a class="reference internal" href="#ctypes.c_double" title="ctypes.c_double"><code class="xref py py-class docutils literal"><span class="pre">c_double</span></code></a>的别名。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_float"><span class="yiyi-st" id="yiyi-636"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_float</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-637">表示C <code class="xref c c-type docutils literal"><span class="pre">float</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-638">构造函数接受一个可选的浮点初始值设定项。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_int"><span class="yiyi-st" id="yiyi-639"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_int</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-640">表示C <code class="xref c c-type docutils literal"><span class="pre">有符号的</span> <span class="pre">int</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-641">构造函数接受一个可选的整数初始值设定项;没有溢出检查完成。</span><span class="yiyi-st" id="yiyi-642">在<code class="docutils literal"><span class="pre">sizeof(int)</span> <span class="pre">==</span> <span class="pre">sizeof(long)</span></code>的平台上,它是<a class="reference internal" href="#ctypes.c_long" title="ctypes.c_long"><code class="xref py py-class docutils literal"><span class="pre">c_long</span></code></a></span></p></dd></dl><dl class="class"><dt id="ctypes.c_int8"><span class="yiyi-st" id="yiyi-643"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_int8</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-644">表示C 8位<code class="xref c c-type docutils literal"><span class="pre">有符号</span> <span class="pre">int</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-645">通常是<a class="reference internal" href="#ctypes.c_byte" title="ctypes.c_byte"><code class="xref py py-class docutils literal"><span class="pre">c_byte</span></code></a>的别名。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_int16"><span class="yiyi-st" id="yiyi-646"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_int16</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-647">表示C 16位<code class="xref c c-type docutils literal"><span class="pre">有符号</span> <span class="pre">int</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-648">通常是<a class="reference internal" href="#ctypes.c_short" title="ctypes.c_short"><code class="xref py py-class docutils literal"><span class="pre">c_short</span></code></a>的别名。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_int32"><span class="yiyi-st" id="yiyi-649"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_int32</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-650">表示C 32位<code class="xref c c-type docutils literal"><span class="pre">有符号</span> <span class="pre">int</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-651">通常是<a class="reference internal" href="#ctypes.c_int" title="ctypes.c_int"><code class="xref py py-class docutils literal"><span class="pre">c_int</span></code></a>的别名。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_int64"><span class="yiyi-st" id="yiyi-652"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_int64</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-653">表示C 64位<code class="xref c c-type docutils literal"><span class="pre">有符号</span> <span class="pre">int</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-654">通常是<a class="reference internal" href="#ctypes.c_longlong" title="ctypes.c_longlong"><code class="xref py py-class docutils literal"><span class="pre">c_longlong</span></code></a>的别名。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_long"><span class="yiyi-st" id="yiyi-655"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_long</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-656">表示C <code class="xref c c-type docutils literal"><span class="pre">signed</span> <span class="pre">long</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-657">构造函数接受一个可选的整数初始值设定项;没有溢出检查完成。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_longlong"><span class="yiyi-st" id="yiyi-658"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_longlong</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-659">表示C <code class="xref c c-type docutils literal"><span class="pre">有符号</span> <span class="pre">长</span> <span class="pre">长</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-660">构造函数接受一个可选的整数初始值设定项;没有溢出检查完成。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_short"><span class="yiyi-st" id="yiyi-661"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_short</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-662">表示C <code class="xref c c-type docutils literal"><span class="pre">signed</span> <span class="pre">short</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-663">构造函数接受一个可选的整数初始值设定项;没有溢出检查完成。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_size_t"><span class="yiyi-st" id="yiyi-664"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_size_t</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-665">表示C <code class="xref c c-type docutils literal"><span class="pre">size_t</span></code>数据类型。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_ssize_t"><span class="yiyi-st" id="yiyi-666"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_ssize_t</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-667">表示C <code class="xref c c-type docutils literal"><span class="pre">ssize_t</span></code>数据类型。</span></p><div class="versionadded"><p><span class="yiyi-st" id="yiyi-668"><span class="versionmodified">版本3.2中的新功能。</span></span></p></div></dd></dl><dl class="class"><dt id="ctypes.c_ubyte"><span class="yiyi-st" id="yiyi-669"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_ubyte</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-670">表示C <code class="xref c c-type docutils literal"><span class="pre">无符号</span> <span class="pre">char</span></code>数据类型,它将该值解释为小整数。</span><span class="yiyi-st" id="yiyi-671">构造函数接受一个可选的整数初始值设定项;没有溢出检查完成。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_uint"><span class="yiyi-st" id="yiyi-672"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_uint</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-673">表示C <code class="xref c c-type docutils literal"><span class="pre">无符号</span> <span class="pre">int</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-674">构造函数接受一个可选的整数初始值设定项;没有溢出检查完成。</span><span class="yiyi-st" id="yiyi-675">在<code class="docutils literal"><span class="pre">sizeof(int)</span> <span class="pre">==</span> <span class="pre">sizeof(long)</span></code>的平台上,它是<a class="reference internal" href="#ctypes.c_ulong" title="ctypes.c_ulong"><code class="xref py py-class docutils literal"><span class="pre">c_ulong</span></code></a></span></p></dd></dl><dl class="class"><dt id="ctypes.c_uint8"><span class="yiyi-st" id="yiyi-676"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_uint8</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-677">Represents the C 8-bit <code class="xref c c-type docutils literal"><span class="pre">unsigned</span> <span class="pre">int</span></code> datatype. </span><span class="yiyi-st" id="yiyi-678">通常是<a class="reference internal" href="#ctypes.c_ubyte" title="ctypes.c_ubyte"><code class="xref py py-class docutils literal"><span class="pre">c_ubyte</span></code></a>的别名。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_uint16"><span class="yiyi-st" id="yiyi-679"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_uint16</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-680">表示C 16位<code class="xref c c-type docutils literal"><span class="pre">无符号</span> <span class="pre">int</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-681">通常是<a class="reference internal" href="#ctypes.c_ushort" title="ctypes.c_ushort"><code class="xref py py-class docutils literal"><span class="pre">c_ushort</span></code></a>的别名。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_uint32"><span class="yiyi-st" id="yiyi-682"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_uint32</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-683">表示C 32位<code class="xref c c-type docutils literal"><span class="pre">无符号</span> <span class="pre">int</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-684">通常是<a class="reference internal" href="#ctypes.c_uint" title="ctypes.c_uint"><code class="xref py py-class docutils literal"><span class="pre">c_uint</span></code></a>的别名。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_uint64"><span class="yiyi-st" id="yiyi-685"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_uint64</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-686">表示C 64位<code class="xref c c-type docutils literal"><span class="pre">无符号</span> <span class="pre">int</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-687">通常是<a class="reference internal" href="#ctypes.c_ulonglong" title="ctypes.c_ulonglong"><code class="xref py py-class docutils literal"><span class="pre">c_ulonglong</span></code></a>的别名。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_ulong"><span class="yiyi-st" id="yiyi-688"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_ulong</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-689">表示C <code class="xref c c-type docutils literal"><span class="pre">无符号</span> <span class="pre">long</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-690">构造函数接受一个可选的整数初始值设定项;没有溢出检查完成。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_ulonglong"><span class="yiyi-st" id="yiyi-691"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_ulonglong</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-692">表示C <code class="xref c c-type docutils literal"><span class="pre">无符号</span> <span class="pre">long</span> <span class="pre">long</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-693">构造函数接受一个可选的整数初始值设定项;没有溢出检查完成。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_ushort"><span class="yiyi-st" id="yiyi-694"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_ushort</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-695">表示C <code class="xref c c-type docutils literal"><span class="pre">无符号</span> <span class="pre">short</span></code>数据类型。</span><span class="yiyi-st" id="yiyi-696">构造函数接受一个可选的整数初始值设定项;没有溢出检查完成。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_void_p"><span class="yiyi-st" id="yiyi-697"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_void_p</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-698">表示C <code class="xref c c-type docutils literal"><span class="pre">void</span> <span class="pre">*</span></code>类型。</span><span class="yiyi-st" id="yiyi-699">该值表示为整数。</span><span class="yiyi-st" id="yiyi-700">构造函数接受一个可选的整数初始值设定项。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_wchar"><span class="yiyi-st" id="yiyi-701"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_wchar</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-702">表示C <code class="xref c c-type docutils literal"><span class="pre">wchar_t</span></code>数据类型,并将该值解释为单个字符的unicode字符串。</span><span class="yiyi-st" id="yiyi-703">构造函数接受一个可选的字符串初始值设定项,字符串的长度必须恰好为一个字符。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_wchar_p"><span class="yiyi-st" id="yiyi-704"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_wchar_p</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-705">表示C <code class="xref c c-type docutils literal"><span class="pre">wchar_t</span> <span class="pre">*</span></code>数据类型,它必须是指向零终止的宽字符字符串的指针。</span><span class="yiyi-st" id="yiyi-706">构造函数接受一个整数地址或一个字符串。</span></p></dd></dl><dl class="class"><dt id="ctypes.c_bool"><span class="yiyi-st" id="yiyi-707"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">c_bool</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-708">表示C <code class="xref c c-type docutils literal"><span class="pre">bool</span></code>数据类型(更准确地说,来自C99的<code class="xref c c-type docutils literal"><span class="pre">_Bool</span></code>)。</span><span class="yiyi-st" id="yiyi-709">它的值可以是<code class="docutils literal"><span class="pre">True</span></code>或<code class="docutils literal"><span class="pre">False</span></code>,并且构造函数接受任何具有真值的对象。</span></p></dd></dl><dl class="class"><dt id="ctypes.HRESULT"><span class="yiyi-st" id="yiyi-710"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">HRESULT</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-711">仅限Windows:表示一个<code class="xref c c-type docutils literal"><span class="pre">HRESULT</span></code>值,其中包含函数或方法调用的成功或错误信息。</span></p></dd></dl><dl class="class"><dt id="ctypes.py_object"><span class="yiyi-st" id="yiyi-712"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">py_object</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-713">表示C <a class="reference internal" href="../c-api/structures.html#c.PyObject" title="PyObject"><code class="xref c c-type docutils literal"><span class="pre">PyObject</span> <span class="pre">*</span></code></a>数据类型。</span><span class="yiyi-st" id="yiyi-714">不带参数调用它会创建一个<code class="docutils literal"><span class="pre">NULL</span></code> <a class="reference internal" href="../c-api/structures.html#c.PyObject" title="PyObject"><code class="xref c c-type docutils literal"><span class="pre">PyObject</span> <span class="pre">*</span></code></a>指针。</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-715"><code class="xref py py-mod docutils literal"><span class="pre">ctypes.wintypes</span></code>模块提供了一些其他特定于Windows的数据类型,例如<code class="xref c c-type docutils literal"><span class="pre">HWND</span></code>,<code class="xref c c-type docutils literal"><span class="pre">WPARAM</span></code>或<code class="xref c c-type docutils literal"><span class="pre">DWORD</span></code> 。</span><span class="yiyi-st" id="yiyi-716">还定义了一些有用的结构,如<code class="xref c c-type docutils literal"><span class="pre">MSG</span></code>或<code class="xref c c-type docutils literal"><span class="pre">RECT</span></code>。</span></p></div><div class="section" id="structured-data-types"><h3><span class="yiyi-st" id="yiyi-717">16.16.2.8. </span><span class="yiyi-st" id="yiyi-718">结构化数据类型</span></h3><dl class="class"><dt id="ctypes.Union"><span class="yiyi-st" id="yiyi-719"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">Union</code><span class="sig-paren">(</span><em>*args</em>, <em>**kw</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-720">本地字节顺序的联合的抽象基类。</span></p></dd></dl><dl class="class"><dt id="ctypes.BigEndianStructure"><span class="yiyi-st" id="yiyi-721"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">BigEndianStructure</code><span class="sig-paren">(</span><em>*args</em>, <em>**kw</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-722">用于<em>big endian</em>字节顺序的结构的抽象基类。</span></p></dd></dl><dl class="class"><dt id="ctypes.LittleEndianStructure"><span class="yiyi-st" id="yiyi-723"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">LittleEndianStructure</code><span class="sig-paren">(</span><em>*args</em>, <em>**kw</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-724"><em>小端字节顺序的结构的抽象基类。</em></span></p></dd></dl><p><span class="yiyi-st" id="yiyi-725">具有非本地字节顺序的结构不能包含指针类型字段或包含指针类型字段的任何其他数据类型。</span></p><dl class="class"><dt id="ctypes.Structure"><span class="yiyi-st" id="yiyi-726"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">Structure</code><span class="sig-paren">(</span><em>*args</em>, <em>**kw</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-727"><em>native</em>字节顺序的结构的抽象基类。</span></p><p><span class="yiyi-st" id="yiyi-728">具体结构和联合类型必须通过继承这些类型之一来创建,并至少定义一个<a class="reference internal" href="#ctypes.Structure._fields_" title="ctypes.Structure._fields_"><code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code></a>类变量。</span><span class="yiyi-st" id="yiyi-729"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>将创建<a class="reference internal" href="../glossary.html#term-descriptor"><span class="xref std std-term">descriptor</span></a>,允许通过直接属性访问来读写字段。</span><span class="yiyi-st" id="yiyi-730">这些是</span></p><dl class="attribute"><dt id="ctypes.Structure._fields_"><span class="yiyi-st" id="yiyi-731"> <code class="descname">_fields_</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-732">定义结构字段的序列。</span><span class="yiyi-st" id="yiyi-733">这些项目必须是2元组或3元组。</span><span class="yiyi-st" id="yiyi-734">第一个项目是字段的名称,第二个项目指定字段的类型;它可以是任何ctypes数据类型。</span></p><p><span class="yiyi-st" id="yiyi-735">对于像<a class="reference internal" href="#ctypes.c_int" title="ctypes.c_int"><code class="xref py py-class docutils literal"><span class="pre">c_int</span></code></a>这样的整数类型字段,可以给出第三个可选项。</span><span class="yiyi-st" id="yiyi-736">它必须是一个定义字段位宽的小正整数。</span></p><p><span class="yiyi-st" id="yiyi-737">一个结构或联合中的字段名称必须是唯一的。</span><span class="yiyi-st" id="yiyi-738">这不检查,名称重复时只能访问一个字段。</span></p><p><span class="yiyi-st" id="yiyi-739">可以在定义Structure子类的类语句之后定义<a class="reference internal" href="#ctypes.Structure._fields_" title="ctypes.Structure._fields_"><code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code></a>类变量<em>,这允许直接或间接引用它们自己的数据类型:</em></span></p><pre><code class="language-python"><span></span><span class="k">class</span> <span class="nc">List</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
|
||
<span class="k">pass</span>
|
||
<span class="n">List</span><span class="o">.</span><span class="n">_fields_</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">"pnext"</span><span class="p">,</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">List</span><span class="p">)),</span>
|
||
<span class="o">...</span>
|
||
<span class="p">]</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-740">The <a class="reference internal" href="#ctypes.Structure._fields_" title="ctypes.Structure._fields_"><code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code></a> class variable must, however, be defined before the type is first used (an instance is created, <a class="reference internal" href="#ctypes.sizeof" title="ctypes.sizeof"><code class="xref py py-func docutils literal"><span class="pre">sizeof()</span></code></a> is called on it, and so on). </span><span class="yiyi-st" id="yiyi-741">稍后分配给<a class="reference internal" href="#ctypes.Structure._fields_" title="ctypes.Structure._fields_"><code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code></a>类变量将引发一个AttributeError。</span></p><p><span class="yiyi-st" id="yiyi-742">可以定义结构类型的子子类,它们继承基类的字段加上在子子类中定义的<a class="reference internal" href="#ctypes.Structure._fields_" title="ctypes.Structure._fields_"><code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code></a>(如果有的话)。</span></p></dd></dl><dl class="attribute"><dt id="ctypes.Structure._pack_"><span class="yiyi-st" id="yiyi-743"> <code class="descname">_pack_</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-744">一个可选的小整数,它允许覆盖实例中结构字段的对齐方式。</span><span class="yiyi-st" id="yiyi-745"><a class="reference internal" href="#ctypes.Structure._fields_" title="ctypes.Structure._fields_"><code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code></a>分配时必须已经定义<a class="reference internal" href="#ctypes.Structure._pack_" title="ctypes.Structure._pack_"><code class="xref py py-attr docutils literal"><span class="pre">_pack_</span></code></a>,否则它将不起作用。</span></p></dd></dl><dl class="attribute"><dt id="ctypes.Structure._anonymous_"><span class="yiyi-st" id="yiyi-746"> <code class="descname">_anonymous_</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-747">列出未命名(匿名)字段名称的可选序列。</span><span class="yiyi-st" id="yiyi-748"><a class="reference internal" href="#ctypes.Structure._anonymous_" title="ctypes.Structure._anonymous_"><code class="xref py py-attr docutils literal"><span class="pre">_anonymous_</span></code></a> must be already defined when <a class="reference internal" href="#ctypes.Structure._fields_" title="ctypes.Structure._fields_"><code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code></a> is assigned, otherwise it will have no effect.</span></p><p><span class="yiyi-st" id="yiyi-749">此变量中列出的字段必须是结构或联合类型字段。</span><span class="yiyi-st" id="yiyi-750"><a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>将在结构类型中创建描述符,允许直接访问嵌套字段,而不需要创建结构或联合字段。</span></p><p><span class="yiyi-st" id="yiyi-751">这是一个示例类型(Windows):</span></p><pre><code class="language-python"><span></span><span class="k">class</span> <span class="nc">_U</span><span class="p">(</span><span class="n">Union</span><span class="p">):</span>
|
||
<span class="n">_fields_</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">"lptdesc"</span><span class="p">,</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">TYPEDESC</span><span class="p">)),</span>
|
||
<span class="p">(</span><span class="s2">"lpadesc"</span><span class="p">,</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">ARRAYDESC</span><span class="p">)),</span>
|
||
<span class="p">(</span><span class="s2">"hreftype"</span><span class="p">,</span> <span class="n">HREFTYPE</span><span class="p">)]</span>
|
||
|
||
<span class="k">class</span> <span class="nc">TYPEDESC</span><span class="p">(</span><span class="n">Structure</span><span class="p">):</span>
|
||
<span class="n">_anonymous_</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"u"</span><span class="p">,)</span>
|
||
<span class="n">_fields_</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">"u"</span><span class="p">,</span> <span class="n">_U</span><span class="p">),</span>
|
||
<span class="p">(</span><span class="s2">"vt"</span><span class="p">,</span> <span class="n">VARTYPE</span><span class="p">)]</span>
|
||
</code></pre><p><span class="yiyi-st" id="yiyi-752"><code class="docutils literal"><span class="pre">TYPEDESC</span></code>结构描述了一个COM数据类型,<code class="docutils literal"><span class="pre">vt</span></code>字段指定哪个联合字段是有效的。</span><span class="yiyi-st" id="yiyi-753">由于<code class="docutils literal"><span class="pre">u</span></code>字段被定义为匿名字段,现在可以直接访问TYPEDESC实例之外的成员。</span><span class="yiyi-st" id="yiyi-754"><code class="docutils literal"><span class="pre">td.lptdesc</span></code> and <code class="docutils literal"><span class="pre">td.u.lptdesc</span></code> are equivalent, but the former is faster since it does not need to create a temporary union instance:</span></p><pre><code class="language-python"><span></span><span class="n">td</span> <span class="o">=</span> <span class="n">TYPEDESC</span><span class="p">()</span>
|
||
<span class="n">td</span><span class="o">.</span><span class="n">vt</span> <span class="o">=</span> <span class="n">VT_PTR</span>
|
||
<span class="n">td</span><span class="o">.</span><span class="n">lptdesc</span> <span class="o">=</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">some_type</span><span class="p">)</span>
|
||
<span class="n">td</span><span class="o">.</span><span class="n">u</span><span class="o">.</span><span class="n">lptdesc</span> <span class="o">=</span> <span class="n">POINTER</span><span class="p">(</span><span class="n">some_type</span><span class="p">)</span>
|
||
</code></pre></dd></dl><p><span class="yiyi-st" id="yiyi-755">可以定义结构的子子类,它们继承基类的字段。</span><span class="yiyi-st" id="yiyi-756">如果子类定义具有单独的<a class="reference internal" href="#ctypes.Structure._fields_" title="ctypes.Structure._fields_"><code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code></a>变量,则在此指定的字段将附加到基类的字段中。</span></p><p><span class="yiyi-st" id="yiyi-757">结构和联合构造函数接受位置和关键字参数。</span><span class="yiyi-st" id="yiyi-758">位置参数用于按照出现在<a class="reference internal" href="#ctypes.Structure._fields_" title="ctypes.Structure._fields_"><code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code></a>中的顺序初始化成员字段。</span><span class="yiyi-st" id="yiyi-759">构造函数中的关键字参数被解释为属性赋值,所以它们将初始化具有相同名称的<a class="reference internal" href="#ctypes.Structure._fields_" title="ctypes.Structure._fields_"><code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code></a>,或为<a class="reference internal" href="#ctypes.Structure._fields_" title="ctypes.Structure._fields_"><code class="xref py py-attr docutils literal"><span class="pre">_fields_</span></code></a>中不存在的名称创建新属性。</span></p></dd></dl></div><div class="section" id="arrays-and-pointers"><h3><span class="yiyi-st" id="yiyi-760">16.16.2.9. </span><span class="yiyi-st" id="yiyi-761">数组和指针</span></h3><dl class="class"><dt id="ctypes.Array"><span class="yiyi-st" id="yiyi-762"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">Array</code><span class="sig-paren">(</span><em>*args</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-763">数组的抽象基类。</span></p><p><span class="yiyi-st" id="yiyi-764">推荐的创建具体数组类型的方法是将任何<a class="reference internal" href="#module-ctypes" title="ctypes: A foreign function library for Python."><code class="xref py py-mod docutils literal"><span class="pre">ctypes</span></code></a>数据类型与正整数相乘。</span><span class="yiyi-st" id="yiyi-765">或者,您可以继承此类型并定义<a class="reference internal" href="#ctypes.Array._length_" title="ctypes.Array._length_"><code class="xref py py-attr docutils literal"><span class="pre">_length_</span></code></a>和<a class="reference internal" href="#ctypes.Array._type_" title="ctypes.Array._type_"><code class="xref py py-attr docutils literal"><span class="pre">_type_</span></code></a>类变量。</span><span class="yiyi-st" id="yiyi-766">数组元素可以使用标准的下标和切片访问来读写;对于片段读取,结果对象本身不是<em></em>本身就是<a class="reference internal" href="#ctypes.Array" title="ctypes.Array"><code class="xref py py-class docutils literal"><span class="pre">Array</span></code></a>。</span></p><dl class="attribute"><dt id="ctypes.Array._length_"><span class="yiyi-st" id="yiyi-767"> <code class="descname">_length_</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-768">指定数组中元素数量的正整数。</span><span class="yiyi-st" id="yiyi-769">超出范围的下标导致<a class="reference internal" href="exceptions.html#IndexError" title="IndexError"><code class="xref py py-exc docutils literal"><span class="pre">IndexError</span></code></a>。</span><span class="yiyi-st" id="yiyi-770">将由<a class="reference internal" href="functions.html#len" title="len"><code class="xref py py-func docutils literal"><span class="pre">len()</span></code></a>返回。</span></p></dd></dl><dl class="attribute"><dt id="ctypes.Array._type_"><span class="yiyi-st" id="yiyi-771"> <code class="descname">_type_</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-772">指定数组中每个元素的类型。</span></p></dd></dl><p><span class="yiyi-st" id="yiyi-773">数组子类的构造函数接受位置参数,用于按顺序初始化元素。</span></p></dd></dl><dl class="class"><dt id="ctypes._Pointer"><span class="yiyi-st" id="yiyi-774"> <em class="property">class </em><code class="descclassname">ctypes.</code><code class="descname">_Pointer</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-775">指针的私有抽象基类。</span></p><p><span class="yiyi-st" id="yiyi-776">具体的指针类型通过调用带有指向类型的<a class="reference internal" href="#ctypes.POINTER" title="ctypes.POINTER"><code class="xref py py-func docutils literal"><span class="pre">POINTER()</span></code></a>来创建;这是通过<a class="reference internal" href="#ctypes.pointer" title="ctypes.pointer"><code class="xref py py-func docutils literal"><span class="pre">pointer()</span></code></a>自动完成的。</span></p><p><span class="yiyi-st" id="yiyi-777">如果指针指向数组,则可以使用标准下标和切片访问来读取和写入其元素。</span><span class="yiyi-st" id="yiyi-778">指针对象没有大小,所以<a class="reference internal" href="functions.html#len" title="len"><code class="xref py py-func docutils literal"><span class="pre">len()</span></code></a>会引发<a class="reference internal" href="exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal"><span class="pre">TypeError</span></code></a>。</span><span class="yiyi-st" id="yiyi-779">负下标将从内存<em>读取之前 T0>指针(如C)中,和外的范围的下标将可能与访问冲突崩溃(如果你幸运的话)。</em></span></p><dl class="attribute"><dt id="ctypes._Pointer._type_"><span class="yiyi-st" id="yiyi-780"> <code class="descname">_type_</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-781">指定指向的类型。</span></p></dd></dl><dl class="attribute"><dt id="ctypes._Pointer.contents"><span class="yiyi-st" id="yiyi-782"> <code class="descname">contents</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-783">返回要指向点的对象。</span><span class="yiyi-st" id="yiyi-784">分配给该属性会将指针更改为指向指定的对象。</span></p></dd></dl></dd></dl></div></div></div></div> |