“Python/docs/3.9/library/ctypes”的版本间差异

来自菜鸟教程
Python/docs/3.9/library/ctypes
跳转至:导航、​搜索
(autoload)
 
(Page commit)
 
第1行: 第1行:
 +
{{DISPLAYTITLE:ctypes — Python 的外部函数库 — Python 文档}}
 
<div id="module-ctypes" class="section">
 
<div id="module-ctypes" class="section">
  
 
<span id="ctypes-a-foreign-function-library-for-python"></span>
 
<span id="ctypes-a-foreign-function-library-for-python"></span>
= [[#module-ctypes|<code>ctypes</code>]] --- A foreign function library for Python =
+
= ctypes Python 的外部函数库 =
  
[[#module-ctypes|<code>ctypes</code>]] is a foreign function library for Python. It provides C compatible
+
 
data types, and allows calling functions in DLLs or shared libraries. It can be
+
-----
used to wrap these libraries in pure Python.
+
 
 +
[[#module-ctypes|ctypes]] Python 的外部函数库。 它提供与 C 兼容的数据类型,并允许调用 DLL 或共享库中的函数。 它可用于将这些库包装在纯 Python 中。
  
 
<div id="ctypes-tutorial" class="section">
 
<div id="ctypes-tutorial" class="section">
  
 
<span id="ctypes-ctypes-tutorial"></span>
 
<span id="ctypes-ctypes-tutorial"></span>
== ctypes tutorial ==
+
== ctypes教程 ==
  
Note: The code samples in this tutorial use [[../doctest#module-doctest|<code>doctest</code>]] to make sure that
+
注意:本教程中的代码示例使用 [[../doctest#module-doctest|doctest]] 来确保它们确实有效。 由于某些代码示例在 Linux、Windows 或 macOS 下的行为不同,因此它们在注释中包含 doctest 指令。
they actually work. Since some code samples behave differently under Linux,
 
Windows, or Mac OS X, they contain doctest directives in comments.
 
  
Note: Some code samples reference the ctypes [[#ctypes.c_int|<code>c_int</code>]] type. On platforms
+
注意:一些代码示例引用了 ctypes [[#ctypes.c_int|c_int]] 类型。 在 <code>sizeof(long) == sizeof(int)</code> 它是 [[#ctypes.c_long|c_long]] 的别名的平台上。 因此,如果您期望 [[#ctypes.c_int|c_int]] 打印 [[#ctypes.c_long|c_long]],您不应该感到困惑——它们实际上是相同的类型。
where <code>sizeof(long) == sizeof(int)</code> it is an alias to [[#ctypes.c_long|<code>c_long</code>]].
 
So, you should not be confused if [[#ctypes.c_long|<code>c_long</code>]] is printed if you would expect
 
[[#ctypes.c_int|<code>c_int</code>]] --- they are actually the same type.
 
  
 
<div id="loading-dynamic-link-libraries" class="section">
 
<div id="loading-dynamic-link-libraries" class="section">
  
 
<span id="ctypes-loading-dynamic-link-libraries"></span>
 
<span id="ctypes-loading-dynamic-link-libraries"></span>
=== Loading dynamic link libraries ===
+
=== 加载动态链接库 ===
  
[[#module-ctypes|<code>ctypes</code>]] exports the ''cdll'', and on Windows ''windll'' and ''oledll''
+
[[#module-ctypes|ctypes]] 导出 ''cdll'',在 Windows ''windll'' ''oledll'' 对象上,用于加载动态链接库。
objects, for loading dynamic link libraries.
 
  
You load libraries by accessing them as attributes of these objects. ''cdll''
+
您可以通过将库作为这些对象的属性进行访问来加载库。 ''cdll'' 加载使用标准 <code>cdecl</code> 调用约定导出函数的库,而 ''windll'' 库使用 <code>stdcall</code> 调用约定调用函数。 ''oledll'' 也使用 <code>stdcall</code> 调用约定,并假设函数返回 Windows <code>HRESULT</code> 错误代码。 错误代码用于在函数调用失败时自动引发 [[../exceptions#OSError|OSError]] 异常。
loads libraries which export functions using the standard <code>cdecl</code> calling
 
convention, while ''windll'' libraries call functions using the <code>stdcall</code>
 
calling convention. ''oledll'' also uses the <code>stdcall</code> calling convention, and
 
assumes the functions return a Windows <code>HRESULT</code> error code. The error
 
code is used to automatically raise an [[../exceptions#OSError|<code>OSError</code>]] exception when the
 
function call fails.
 
  
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<span class="versionmodified changed">3.3 版更改: </span>Windows errors used to raise [[../exceptions#WindowsError|<code>WindowsError</code>]], which is now an alias
+
<span class="versionmodified changed">3.3 版更改:</span>Windows 错误用于引发 [[../exceptions#WindowsError|WindowsError]],现在是 [[../exceptions#OSError|OSError]] 的别名。
of [[../exceptions#OSError|<code>OSError</code>]].
 
  
  
 
</div>
 
</div>
Here are some examples for Windows. Note that <code>msvcrt</code> is the MS standard C
+
下面是一些适用于 Windows 的示例。 请注意,<code>msvcrt</code> 是包含大多数标准 C 函数的 MS 标准 C 库,并使用 cdecl 调用约定:
library containing most standard C functions, and uses the cdecl calling
 
convention:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第53行: 第40行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes import *
+
<syntaxhighlight lang="python3">>>> from ctypes import *
&gt;&gt;&gt; print(windll.kernel32)   
+
>>> print(windll.kernel32)   
&lt;WinDLL 'kernel32', handle ... at ...&gt;
+
<WinDLL 'kernel32', handle ... at ...>
&gt;&gt;&gt; print(cdll.msvcrt)       
+
>>> print(cdll.msvcrt)       
&lt;CDLL 'msvcrt', handle ... at ...&gt;
+
<CDLL 'msvcrt', handle ... at ...>
&gt;&gt;&gt; libc = cdll.msvcrt       
+
>>> libc = cdll.msvcrt       
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Windows appends the usual <code>.dll</code> file suffix automatically.
+
Windows 会自动附加通常的 <code>.dll</code> 文件后缀。
  
 
<div class="admonition note">
 
<div class="admonition note">
  
注解
+
笔记
  
Accessing the standard C library through <code>cdll.msvcrt</code> will use an
+
通过 <code>cdll.msvcrt</code> 访问标准 C 库将使用该库的过时版本,该版本可能与 Python 使用的版本不兼容。 在可能的情况下,使用本机 Python 功能,或者导入并使用 <code>msvcrt</code> 模块。
outdated version of the library that may be incompatible with the one
 
being used by Python. Where possible, use native Python functionality,
 
or else import and use the <code>msvcrt</code> module.
 
  
  
 
</div>
 
</div>
On Linux, it is required to specify the filename ''including'' the extension to
+
Linux 上,需要指定文件名 ''包括'' 扩展名才能加载库,因此不能使用属性访问来加载库。 应该使用 dll 加载器的 <code>LoadLibrary()</code> 方法,或者您应该通过调用构造函数创建 CDLL 的实例来加载库:
load a library, so attribute access can not be used to load libraries. Either the
 
<code>LoadLibrary()</code> method of the dll loaders should be used, or you should load
 
the library by creating an instance of CDLL by calling the constructor:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第86行: 第67行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; cdll.LoadLibrary(&quot;libc.so.6&quot;)   
+
<syntaxhighlight lang="python3">>>> cdll.LoadLibrary("libc.so.6")   
&lt;CDLL 'libc.so.6', handle ... at ...&gt;
+
<CDLL 'libc.so.6', handle ... at ...>
&gt;&gt;&gt; libc = CDLL(&quot;libc.so.6&quot;)       
+
>>> libc = CDLL("libc.so.6")       
&gt;&gt;&gt; libc                           
+
>>> libc                           
&lt;CDLL 'libc.so.6', handle ... at ...&gt;
+
<CDLL 'libc.so.6', handle ... at ...>
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
第101行: 第82行:
  
 
<span id="ctypes-accessing-functions-from-loaded-dlls"></span>
 
<span id="ctypes-accessing-functions-from-loaded-dlls"></span>
=== Accessing functions from loaded dlls ===
+
=== 从加载的 dll 访问函数 ===
  
Functions are accessed as attributes of dll objects:
+
函数作为 dll 对象的属性被访问:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第109行: 第90行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes import *
+
<syntaxhighlight lang="python3">>>> from ctypes import *
&gt;&gt;&gt; libc.printf
+
>>> libc.printf
&lt;_FuncPtr object at 0x...&gt;
+
<_FuncPtr object at 0x...>
&gt;&gt;&gt; print(windll.kernel32.GetModuleHandleA)   
+
>>> print(windll.kernel32.GetModuleHandleA)   
&lt;_FuncPtr object at 0x...&gt;
+
<_FuncPtr object at 0x...>
&gt;&gt;&gt; print(windll.kernel32.MyOwnFunction)     
+
>>> print(windll.kernel32.MyOwnFunction)     
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
   File &quot;ctypes.py&quot;, line 239, in __getattr__
+
   File "ctypes.py", line 239, in __getattr__
 
     func = _StdcallFuncPtr(name, self)
 
     func = _StdcallFuncPtr(name, self)
 
AttributeError: function 'MyOwnFunction' not found
 
AttributeError: function 'MyOwnFunction' not found
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Note that win32 system dlls like <code>kernel32</code> and <code>user32</code> often export ANSI
+
请注意,像 <code>kernel32</code> <code>user32</code> 这样的 win32 系统 dll 通常会导出函数的 ANSI UNICODE 版本。 UNICODE 版本在导出时在名称后附加了 <code>W</code>,而 ANSI 版本在导出时在名称后附加了 <code>A</code>win32 <code>GetModuleHandle</code> 函数返回给定模块名称的 ''模块句柄'' ,具有以下 C 原型,并使用宏将其中之一公开为 <code>GetModuleHandle</code>取决于是否定义了 UNICODE:
as well as UNICODE versions of a function. The UNICODE version is exported with
 
an <code>W</code> appended to the name, while the ANSI version is exported with an <code>A</code>
 
appended to the name. The win32 <code>GetModuleHandle</code> function, which returns a
 
''module handle'' for a given module name, has the following C prototype, and a
 
macro is used to expose one of them as <code>GetModuleHandle</code> depending on whether
 
UNICODE is defined or not:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第137行: 第112行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>/* ANSI version */
+
<syntaxhighlight lang="python3">/* ANSI version */
 
HMODULE GetModuleHandleA(LPCSTR lpModuleName);
 
HMODULE GetModuleHandleA(LPCSTR lpModuleName);
 
/* UNICODE version */
 
/* UNICODE version */
HMODULE GetModuleHandleW(LPCWSTR lpModuleName);</pre>
+
HMODULE GetModuleHandleW(LPCWSTR lpModuleName);</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
''windll'' does not try to select one of them by magic, you must access the
+
''windll'' 不会尝试通过魔法选择其中之一,您必须通过显式指定 <code>GetModuleHandleA</code> <code>GetModuleHandleW</code> 来访问您需要的版本,然后用字节或字符串调用它对象分别。
version you need by specifying <code>GetModuleHandleA</code> or <code>GetModuleHandleW</code>
 
explicitly, and then call it with bytes or string objects respectively.
 
  
Sometimes, dlls export functions with names which aren't valid Python
+
有时,dll 导出的函数名称不是有效的 Python 标识符,例如 <code>&quot;??2@YAPAXI@Z&quot;</code>。 在这种情况下,您必须使用 [[../functions#getattr|getattr()]] 来检索函数:
identifiers, like <code>&quot;??2@YAPAXI@Z&quot;</code>. In this case you have to use
 
[[../functions#getattr|<code>getattr()</code>]] to retrieve the function:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第157行: 第128行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; getattr(cdll.msvcrt, &quot;??2@YAPAXI@Z&quot;)   
+
<syntaxhighlight lang="python3">>>> getattr(cdll.msvcrt, "??2@YAPAXI@Z")   
&lt;_FuncPtr object at 0x...&gt;
+
<_FuncPtr object at 0x...>
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
On Windows, some dlls export functions not by name but by ordinal. These
+
Windows 上,一些 dll 不是按名称而是按顺序导出函数。 可以通过使用序号索引 dll 对象来访问这些函数:
functions can be accessed by indexing the dll object with the ordinal number:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第171行: 第141行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; cdll.kernel32[1]   
+
<syntaxhighlight lang="python3">>>> cdll.kernel32[1]   
&lt;_FuncPtr object at 0x...&gt;
+
<_FuncPtr object at 0x...>
&gt;&gt;&gt; cdll.kernel32[0]   
+
>>> cdll.kernel32[0]   
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
   File &quot;ctypes.py&quot;, line 310, in __getitem__
+
   File "ctypes.py", line 310, in __getitem__
 
     func = _StdcallFuncPtr(name, self)
 
     func = _StdcallFuncPtr(name, self)
 
AttributeError: function ordinal 0 not found
 
AttributeError: function ordinal 0 not found
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
第189行: 第159行:
  
 
<span id="ctypes-calling-functions"></span>
 
<span id="ctypes-calling-functions"></span>
=== Calling functions ===
+
=== 调用函数 ===
  
You can call these functions like any other Python callable. This example uses
+
您可以像调用任何其他 Python 可调用函数一样调用这些函数。 此示例使用 <code>time()</code> 函数,该函数返回自 Unix 纪元以来以秒为单位的系统时间,以及 <code>GetModuleHandleA()</code> 函数,该函数返回一个 win32 模块句柄。
the <code>time()</code> function, which returns system time in seconds since the Unix
 
epoch, and the <code>GetModuleHandleA()</code> function, which returns a win32 module
 
handle.
 
  
This example calls both functions with a <code>NULL</code> pointer (<code>None</code> should be used
+
此示例使用 <code>NULL</code> 指针调用这两个函数(<code>None</code> 应用作 <code>NULL</code> 指针):
as the <code>NULL</code> pointer):
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第203行: 第169行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; print(libc.time(None))   
+
<syntaxhighlight lang="python3">>>> print(libc.time(None))   
 
1150640792
 
1150640792
&gt;&gt;&gt; print(hex(windll.kernel32.GetModuleHandleA(None)))   
+
>>> print(hex(windll.kernel32.GetModuleHandleA(None)))   
 
0x1d000000
 
0x1d000000
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
[[../exceptions#ValueError|<code>ValueError</code>]] is raised when you call an <code>stdcall</code> function with the
+
当您使用 <code>cdecl</code> 调用约定调用 <code>stdcall</code> 函数时,会引发 [[../exceptions#ValueError|ValueError]],反之亦然:
<code>cdecl</code> calling convention, or vice versa:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第219行: 第184行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; cdll.kernel32.GetModuleHandleA(None)   
+
<syntaxhighlight lang="python3">>>> cdll.kernel32.GetModuleHandleA(None)   
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
 
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
 
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
&gt;&gt;&gt;
+
>>>
  
&gt;&gt;&gt; windll.msvcrt.printf(b&quot;spam&quot;)   
+
>>> windll.msvcrt.printf(b"spam")   
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
 
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
 
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
To find out the correct calling convention you have to look into the C header
+
要找出正确的调用约定,您必须查看 C 头文件或要调用的函数的文档。
file or the documentation for the function you want to call.
 
  
On Windows, [[#module-ctypes|<code>ctypes</code>]] uses win32 structured exception handling to prevent
+
Windows 上,[[#module-ctypes|ctypes]] 使用 win32 结构化异常处理来防止在使用无效参数值调用函数时由于一般保护错误而导致崩溃:
crashes from general protection faults when functions are called with invalid
 
argument values:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第245行: 第207行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; windll.kernel32.GetModuleHandleA(32)   
+
<syntaxhighlight lang="python3">>>> windll.kernel32.GetModuleHandleA(32)   
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
 
OSError: exception: access violation reading 0x00000020
 
OSError: exception: access violation reading 0x00000020
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
There are, however, enough ways to crash Python with [[#module-ctypes|<code>ctypes</code>]], so you
+
然而,有足够的方法可以使 Python [[#module-ctypes|ctypes]] 崩溃,所以无论如何你都应该小心。 [[../faulthandler#module-faulthandler|faulthandler]] 模块有助于调试崩溃(例如 由错误的 C 库调用产生的分段错误)。
should be careful anyway. The [[../faulthandler#module-faulthandler|<code>faulthandler</code>]] module can be helpful in
 
debugging crashes (e.g. from segmentation faults produced by erroneous C library
 
calls).
 
  
<code>None</code>, integers, bytes objects and (unicode) strings are the only native
+
<code>None</code>、整数、字节对象和(unicode)字符串是唯一可以在这些函数调用中直接用作参数的原生 Python 对象。 <code>None</code> 作为 C <code>NULL</code> 指针传递,字节对象和字符串作为指向包含其数据的内存块的指针传递(<span class="xref c c-texpr">char*</span> <span class="xref c c-texpr">wchar_t* </span>)。 Python 整数作为平台默认的 C <span class="xref c c-texpr">int</span> 类型传递,它们的值被屏蔽以适应 C 类型。
Python objects that can directly be used as parameters in these function calls.
 
<code>None</code> is passed as a C <code>NULL</code> pointer, bytes objects and strings are passed
 
as pointer to the memory block that contains their data (<span class="xref c c-texpr">char*</span> or
 
<span class="xref c c-texpr">wchar_t*</span>). Python integers are passed as the platforms default C
 
<span class="xref c c-texpr">int</span> type, their value is masked to fit into the C type.
 
  
Before we move on calling functions with other parameter types, we have to learn
+
在继续使用其他参数类型调用函数之前,我们必须了解更多关于 [[#module-ctypes|ctypes]] 数据类型的信息。
more about [[#module-ctypes|<code>ctypes</code>]] data types.
 
  
  
第274行: 第227行:
  
 
<span id="ctypes-fundamental-data-types"></span>
 
<span id="ctypes-fundamental-data-types"></span>
=== Fundamental data types ===
+
=== 基本数据类型 ===
  
[[#module-ctypes|<code>ctypes</code>]] defines a number of primitive C compatible data types:
+
[[#module-ctypes|ctypes]] 定义了一些原始的 C 兼容数据类型:
  
 
{|
 
{|
!width="24%"| ctypes type
+
!width="24%"| ctypes 类型
!width="46%"| C type
+
!width="46%"| C型
!width="30%"| Python type
+
!width="30%"| 蟒蛇型
 
|-
 
|-
 
| [[#ctypes.c_bool|<code>c_bool</code>]]
 
| [[#ctypes.c_bool|<code>c_bool</code>]]
| <span class="xref c c-texpr">_Bool</span>
+
| <span class="xref c c-texpr"><span class="kt">_布尔</span></span>
| bool (1)
+
| 布尔 (1)
 
|-
 
|-
 
| [[#ctypes.c_char|<code>c_char</code>]]
 
| [[#ctypes.c_char|<code>c_char</code>]]
| <span class="xref c c-texpr">char</span>
+
| <span class="xref c c-texpr"><span class="kt">字符</span></span>
| 1-character bytes object
+
| 1 个字符的字节对象
 
|-
 
|-
 
| [[#ctypes.c_wchar|<code>c_wchar</code>]]
 
| [[#ctypes.c_wchar|<code>c_wchar</code>]]
 
| <code>wchar_t</code>
 
| <code>wchar_t</code>
| 1-character string
+
| 1 个字符的字符串
 
|-
 
|-
 
| [[#ctypes.c_byte|<code>c_byte</code>]]
 
| [[#ctypes.c_byte|<code>c_byte</code>]]
| <span class="xref c c-texpr">char</span>
+
| <span class="xref c c-texpr"><span class="kt">字符</span></span>
| int
+
| 整数
 
|-
 
|-
 
| [[#ctypes.c_ubyte|<code>c_ubyte</code>]]
 
| [[#ctypes.c_ubyte|<code>c_ubyte</code>]]
| <span class="xref c c-texpr">unsigned char</span>
+
| <span class="xref c c-texpr"><span class="kt">无符号的字符</span></span>
| int
+
| 整数
 
|-
 
|-
 
| [[#ctypes.c_short|<code>c_short</code>]]
 
| [[#ctypes.c_short|<code>c_short</code>]]
| <span class="xref c c-texpr">short</span>
+
| <span class="xref c c-texpr"><span class="kt">短的</span></span>
| int
+
| 整数
 
|-
 
|-
 
| [[#ctypes.c_ushort|<code>c_ushort</code>]]
 
| [[#ctypes.c_ushort|<code>c_ushort</code>]]
| <span class="xref c c-texpr">unsigned short</span>
+
| <span class="xref c c-texpr"><span class="kt">无符号短</span></span>
| int
+
| 整数
 
|-
 
|-
 
| [[#ctypes.c_int|<code>c_int</code>]]
 
| [[#ctypes.c_int|<code>c_int</code>]]
| <span class="xref c c-texpr">int</span>
+
| <span class="xref c c-texpr"><span class="kt">整数</span></span>
| int
+
| 整数
 
|-
 
|-
 
| [[#ctypes.c_uint|<code>c_uint</code>]]
 
| [[#ctypes.c_uint|<code>c_uint</code>]]
| <span class="xref c c-texpr">unsigned int</span>
+
| <span class="xref c c-texpr"><span class="kt">无符号整数</span></span>
| int
+
| 整数
 
|-
 
|-
 
| [[#ctypes.c_long|<code>c_long</code>]]
 
| [[#ctypes.c_long|<code>c_long</code>]]
| <span class="xref c c-texpr">long</span>
+
| <span class="xref c c-texpr"><span class="kt">长</span></span>
| int
+
| 整数
 
|-
 
|-
 
| [[#ctypes.c_ulong|<code>c_ulong</code>]]
 
| [[#ctypes.c_ulong|<code>c_ulong</code>]]
| <span class="xref c c-texpr">unsigned long</span>
+
| <span class="xref c c-texpr"><span class="kt">无符号长</span></span>
| int
+
| 整数
 
|-
 
|-
 
| [[#ctypes.c_longlong|<code>c_longlong</code>]]
 
| [[#ctypes.c_longlong|<code>c_longlong</code>]]
| <code>__int64</code> or <span class="xref c c-texpr">long long</span>
+
| <code>__int64</code> <span class="xref c c-texpr">长长</span>
| int
+
| 整数
 
|-
 
|-
 
| [[#ctypes.c_ulonglong|<code>c_ulonglong</code>]]
 
| [[#ctypes.c_ulonglong|<code>c_ulonglong</code>]]
| <span class="xref c c-texpr">unsigned __int64</span> or
+
| <span class="xref c c-texpr">unsigned __int64</span> <span class="xref c c-texpr">unsigned long long</span>
<span class="xref c c-texpr">unsigned long long</span>
+
| 整数
| int
 
 
|-
 
|-
 
| [[#ctypes.c_size_t|<code>c_size_t</code>]]
 
| [[#ctypes.c_size_t|<code>c_size_t</code>]]
 
| <code>size_t</code>
 
| <code>size_t</code>
| int
+
| 整数
 
|-
 
|-
 
| [[#ctypes.c_ssize_t|<code>c_ssize_t</code>]]
 
| [[#ctypes.c_ssize_t|<code>c_ssize_t</code>]]
| <code>ssize_t</code> or
+
| <code>ssize_t</code> <code>Py_ssize_t</code>
<code>Py_ssize_t</code>
+
| 整数
| int
 
 
|-
 
|-
 
| [[#ctypes.c_float|<code>c_float</code>]]
 
| [[#ctypes.c_float|<code>c_float</code>]]
| <span class="xref c c-texpr">float</span>
+
| <span class="xref c c-texpr"><span class="kt">漂浮</span></span>
| float
+
| 漂浮
 
|-
 
|-
 
| [[#ctypes.c_double|<code>c_double</code>]]
 
| [[#ctypes.c_double|<code>c_double</code>]]
| <span class="xref c c-texpr">double</span>
+
| <span class="xref c c-texpr"><span class="kt">双倍的</span></span>
| float
+
| 漂浮
 
|-
 
|-
 
| [[#ctypes.c_longdouble|<code>c_longdouble</code>]]
 
| [[#ctypes.c_longdouble|<code>c_longdouble</code>]]
| <span class="xref c c-texpr">long double</span>
+
| <span class="xref c c-texpr"><span class="kt">长双</span></span>
| float
+
| 漂浮
 
|-
 
|-
 
| [[#ctypes.c_char_p|<code>c_char_p</code>]]
 
| [[#ctypes.c_char_p|<code>c_char_p</code>]]
| <span class="xref c c-texpr">char*</span> (NUL terminated)
+
| <span class="xref c c-texpr">char*</span>(NUL 终止)
| bytes object or <code>None</code>
+
| 字节对象或 <code>None</code>
 
|-
 
|-
 
| [[#ctypes.c_wchar_p|<code>c_wchar_p</code>]]
 
| [[#ctypes.c_wchar_p|<code>c_wchar_p</code>]]
| <span class="xref c c-texpr">wchar_t*</span> (NUL terminated)
+
| <span class="xref c c-texpr">wchar_t*</span>(NUL 终止)
| string or <code>None</code>
+
| 字符串或 <code>None</code>
 
|-
 
|-
 
| [[#ctypes.c_void_p|<code>c_void_p</code>]]
 
| [[#ctypes.c_void_p|<code>c_void_p</code>]]
| <span class="xref c c-texpr">void*</span>
+
| <span class="xref c c-texpr"><span class="kt">空白</span><span class="p">*</span></span>
| int or <code>None</code>
+
| 整数或 <code>None</code>
 
|}
 
|}
  
# The constructor accepts any object with a truth value.
+
# 构造函数接受任何具有真值的对象。
  
All these types can be created by calling them with an optional initializer of
+
所有这些类型都可以通过使用正确类型和值的可选初始化程序调用它们来创建:
the correct type and value:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第379行: 第329行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; c_int()
+
<syntaxhighlight lang="python3">>>> c_int()
 
c_long(0)
 
c_long(0)
&gt;&gt;&gt; c_wchar_p(&quot;Hello, World&quot;)
+
>>> c_wchar_p("Hello, World")
 
c_wchar_p(140018365411392)
 
c_wchar_p(140018365411392)
&gt;&gt;&gt; c_ushort(-3)
+
>>> c_ushort(-3)
 
c_ushort(65533)
 
c_ushort(65533)
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Since these types are mutable, their value can also be changed afterwards:
+
由于这些类型是可变的,它们的值也可以在之后更改:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第396行: 第346行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; i = c_int(42)
+
<syntaxhighlight lang="python3">>>> i = c_int(42)
&gt;&gt;&gt; print(i)
+
>>> print(i)
 
c_long(42)
 
c_long(42)
&gt;&gt;&gt; print(i.value)
+
>>> print(i.value)
 
42
 
42
&gt;&gt;&gt; i.value = -99
+
>>> i.value = -99
&gt;&gt;&gt; print(i.value)
+
>>> print(i.value)
 
-99
 
-99
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Assigning a new value to instances of the pointer types [[#ctypes.c_char_p|<code>c_char_p</code>]],
+
为指针类型 [[#ctypes.c_char_p|c_char_p]][[#ctypes.c_wchar_p|c_wchar_p]] [[#ctypes.c_void_p|c_void_p]] 的实例分配一个新值会改变它们指向的 ''内存位置'' '']不是内存块的内容''(当然不是,因为Python字节对象是不可变的):
[[#ctypes.c_wchar_p|<code>c_wchar_p</code>]], and [[#ctypes.c_void_p|<code>c_void_p</code>]] changes the ''memory location'' they
 
point to, ''not the contents'' of the memory block (of course not, because Python
 
bytes objects are immutable):
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第418行: 第365行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; s = &quot;Hello, World&quot;
+
<syntaxhighlight lang="python3">>>> s = "Hello, World"
&gt;&gt;&gt; c_s = c_wchar_p(s)
+
>>> c_s = c_wchar_p(s)
&gt;&gt;&gt; print(c_s)
+
>>> print(c_s)
 
c_wchar_p(139966785747344)
 
c_wchar_p(139966785747344)
&gt;&gt;&gt; print(c_s.value)
+
>>> print(c_s.value)
 
Hello World
 
Hello World
&gt;&gt;&gt; c_s.value = &quot;Hi, there&quot;
+
>>> c_s.value = "Hi, there"
&gt;&gt;&gt; print(c_s)              # the memory location has changed
+
>>> print(c_s)              # the memory location has changed
 
c_wchar_p(139966783348904)
 
c_wchar_p(139966783348904)
&gt;&gt;&gt; print(c_s.value)
+
>>> print(c_s.value)
 
Hi, there
 
Hi, there
&gt;&gt;&gt; print(s)                # first object is unchanged
+
>>> print(s)                # first object is unchanged
 
Hello, World
 
Hello, World
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
You should be careful, however, not to pass them to functions expecting pointers
+
但是,您应该小心,不要将它们传递给需要指向可变内存的指针的函数。 如果您需要可变内存块,ctypes 有一个 [[#ctypes.create_string_buffer|create_string_buffer()]] 函数,它以各种方式创建这些。 可以使用 <code>raw</code> 属性访问(或更改)当前内存块内容; 如果要以 NUL 终止的字符串形式访问它,请使用 <code>value</code> 属性:
to mutable memory. If you need mutable memory blocks, ctypes has a
 
[[#ctypes.create_string_buffer|<code>create_string_buffer()</code>]] function which creates these in various ways. The
 
current memory block contents can be accessed (or changed) with the <code>raw</code>
 
property; if you want to access it as NUL terminated string, use the <code>value</code>
 
property:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第447行: 第389行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes import *
+
<syntaxhighlight lang="python3">>>> from ctypes import *
&gt;&gt;&gt; p = create_string_buffer(3)            # create a 3 byte buffer, initialized to NUL bytes
+
>>> p = create_string_buffer(3)            # create a 3 byte buffer, initialized to NUL bytes
&gt;&gt;&gt; print(sizeof(p), repr(p.raw))
+
>>> print(sizeof(p), repr(p.raw))
 
3 b'\x00\x00\x00'
 
3 b'\x00\x00\x00'
&gt;&gt;&gt; p = create_string_buffer(b&quot;Hello&quot;)    # create a buffer containing a NUL terminated string
+
>>> p = create_string_buffer(b"Hello")    # create a buffer containing a NUL terminated string
&gt;&gt;&gt; print(sizeof(p), repr(p.raw))
+
>>> print(sizeof(p), repr(p.raw))
 
6 b'Hello\x00'
 
6 b'Hello\x00'
&gt;&gt;&gt; print(repr(p.value))
+
>>> print(repr(p.value))
 
b'Hello'
 
b'Hello'
&gt;&gt;&gt; p = create_string_buffer(b&quot;Hello&quot;, 10) # create a 10 byte buffer
+
>>> p = create_string_buffer(b"Hello", 10) # create a 10 byte buffer
&gt;&gt;&gt; print(sizeof(p), repr(p.raw))
+
>>> print(sizeof(p), repr(p.raw))
 
10 b'Hello\x00\x00\x00\x00\x00'
 
10 b'Hello\x00\x00\x00\x00\x00'
&gt;&gt;&gt; p.value = b&quot;Hi&quot;
+
>>> p.value = b"Hi"
&gt;&gt;&gt; print(sizeof(p), repr(p.raw))
+
>>> print(sizeof(p), repr(p.raw))
 
10 b'Hi\x00lo\x00\x00\x00\x00\x00'
 
10 b'Hi\x00lo\x00\x00\x00\x00\x00'
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The [[#ctypes.create_string_buffer|<code>create_string_buffer()</code>]] function replaces the <code>c_buffer()</code> function
+
[[#ctypes.create_string_buffer|create_string_buffer()]] 函数替换了 <code>c_buffer()</code> 函数(仍可用作别名),以及早期 ctypes 版本中的 <code>c_string()</code> 函数。 要创建包含 C 类型 <code>wchar_t</code> Unicode 字符的可变内存块,请使用 [[#ctypes.create_unicode_buffer|create_unicode_buffer()]] 函数。
(which is still available as an alias), as well as the <code>c_string()</code> function
 
from earlier ctypes releases. To create a mutable memory block containing
 
unicode characters of the C type <code>wchar_t</code> use the
 
[[#ctypes.create_unicode_buffer|<code>create_unicode_buffer()</code>]] function.
 
  
  
第478行: 第416行:
  
 
<span id="ctypes-calling-functions-continued"></span>
 
<span id="ctypes-calling-functions-continued"></span>
=== Calling functions, continued ===
+
=== 调用函数,续 ===
  
Note that printf prints to the real standard output channel, ''not'' to
+
请注意,printf 打印到真正的标准输出通道,''not'' [[../sys#sys|sys.stdout]],因此这些示例仅适用于控制台提示符,而不适用于 ''IDLE''''PythonWin''
[[../sys#sys|<code>sys.stdout</code>]], so these examples will only work at the console prompt, not
 
from within ''IDLE'' or ''PythonWin'':
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第488行: 第424行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; printf = libc.printf
+
<syntaxhighlight lang="python3">>>> printf = libc.printf
&gt;&gt;&gt; printf(b&quot;Hello, %s\n&quot;, b&quot;World!&quot;)
+
>>> printf(b"Hello, %s\n", b"World!")
 
Hello, World!
 
Hello, World!
 
14
 
14
&gt;&gt;&gt; printf(b&quot;Hello, %S\n&quot;, &quot;World!&quot;)
+
>>> printf(b"Hello, %S\n", "World!")
 
Hello, World!
 
Hello, World!
 
14
 
14
&gt;&gt;&gt; printf(b&quot;%d bottles of beer\n&quot;, 42)
+
>>> printf(b"%d bottles of beer\n", 42)
 
42 bottles of beer
 
42 bottles of beer
 
19
 
19
&gt;&gt;&gt; printf(b&quot;%f bottles of beer\n&quot;, 42.5)
+
>>> printf(b"%f bottles of beer\n", 42.5)
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
 
ArgumentError: argument 2: exceptions.TypeError: Don't know how to convert parameter 2
 
ArgumentError: argument 2: exceptions.TypeError: Don't know how to convert parameter 2
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
As has been mentioned before, all Python types except integers, strings, and
+
如前所述,除整数、字符串和字节对象之外的所有 Python 类型都必须包装在其对应的 [[#module-ctypes|ctypes]] 类型中,以便将它们转换为所需的 C 数据类型:
bytes objects have to be wrapped in their corresponding [[#module-ctypes|<code>ctypes</code>]] type, so
 
that they can be converted to the required C data type:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第515行: 第449行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; printf(b&quot;An int %d, a double %f\n&quot;, 1234, c_double(3.14))
+
<syntaxhighlight lang="python3">>>> printf(b"An int %d, a double %f\n", 1234, c_double(3.14))
 
An int 1234, a double 3.140000
 
An int 1234, a double 3.140000
 
31
 
31
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
第528行: 第462行:
  
 
<span id="ctypes-calling-functions-with-own-custom-data-types"></span>
 
<span id="ctypes-calling-functions-with-own-custom-data-types"></span>
=== Calling functions with your own custom data types ===
+
=== 使用您自己的自定义数据类型调用函数 ===
  
You can also customize [[#module-ctypes|<code>ctypes</code>]] argument conversion to allow instances of
+
您还可以自定义 [[#module-ctypes|ctypes]] 参数转换,以允许将您自己的类的实例用作函数参数。 [[#module-ctypes|ctypes]] 查找 <code>_as_parameter_</code> 属性并将其用作函数参数。 当然,它必须是整数、字符串或字节之一:
your own classes be used as function arguments. [[#module-ctypes|<code>ctypes</code>]] looks for an
 
<code>_as_parameter_</code> attribute and uses this as the function argument. Of
 
course, it must be one of integer, string, or bytes:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第539行: 第470行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; class Bottles:
+
<syntaxhighlight lang="python3">>>> class Bottles:
 
...    def __init__(self, number):
 
...    def __init__(self, number):
 
...        self._as_parameter_ = number
 
...        self._as_parameter_ = number
 
...
 
...
&gt;&gt;&gt; bottles = Bottles(42)
+
>>> bottles = Bottles(42)
&gt;&gt;&gt; printf(b&quot;%d bottles of beer\n&quot;, bottles)
+
>>> printf(b"%d bottles of beer\n", bottles)
 
42 bottles of beer
 
42 bottles of beer
 
19
 
19
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
If you don't want to store the instance's data in the <code>_as_parameter_</code>
+
如果您不想将实例的数据存储在 <code>_as_parameter_</code> 实例变量中,您可以定义一个 [[../functions#property|属性]] ,使该属性在请求时可用。
instance variable, you could define a [[../functions#property|<code>property</code>]] which makes the
 
attribute available on request.
 
  
  
第561行: 第490行:
  
 
<span id="ctypes-specifying-required-argument-types"></span>
 
<span id="ctypes-specifying-required-argument-types"></span>
=== Specifying the required argument types (function prototypes) ===
+
=== 指定所需的参数类型(函数原型) ===
  
It is possible to specify the required argument types of functions exported from
+
可以通过设置 <code>argtypes</code> 属性来指定从 DLL 导出的函数所需的参数类型。
DLLs by setting the <code>argtypes</code> attribute.
 
  
<code>argtypes</code> must be a sequence of C data types (the <code>printf</code> function is
+
<code>argtypes</code> 必须是 C 数据类型的序列(<code>printf</code> 函数在这里可能不是一个很好的例子,因为它根据格式字符串需要一个变量数和不同类型的参数,在另一方面,这对于试验此功能非常方便):
probably not a good example here, because it takes a variable number and
 
different types of parameters depending on the format string, on the other hand
 
this is quite handy to experiment with this feature):
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第575行: 第500行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; printf.argtypes = [c_char_p, c_char_p, c_int, c_double]
+
<syntaxhighlight lang="python3">>>> printf.argtypes = [c_char_p, c_char_p, c_int, c_double]
&gt;&gt;&gt; printf(b&quot;String '%s', Int %d, Double %f\n&quot;, b&quot;Hi&quot;, 10, 2.2)
+
>>> printf(b"String '%s', Int %d, Double %f\n", b"Hi", 10, 2.2)
 
String 'Hi', Int 10, Double 2.200000
 
String 'Hi', Int 10, Double 2.200000
 
37
 
37
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Specifying a format protects against incompatible argument types (just as a
+
指定格式可以防止不兼容的参数类型(就像 C 函数的原型一样),并尝试将参数转换为有效类型:
prototype for a C function), and tries to convert the arguments to valid types:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第591行: 第515行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; printf(b&quot;%d %d %d&quot;, 1, 2, 3)
+
<syntaxhighlight lang="python3">>>> printf(b"%d %d %d", 1, 2, 3)
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
 
ArgumentError: argument 2: exceptions.TypeError: wrong type
 
ArgumentError: argument 2: exceptions.TypeError: wrong type
&gt;&gt;&gt; printf(b&quot;%s %d %f\n&quot;, b&quot;X&quot;, 2, 3)
+
>>> printf(b"%s %d %f\n", b"X", 2, 3)
 
X 2 3.000000
 
X 2 3.000000
 
13
 
13
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
If you have defined your own classes which you pass to function calls, you have
+
如果您定义了自己的类并传递给函数调用,则必须实现一个 <code>from_param()</code> 类方法,以便它们能够在 <code>argtypes</code> 序列中使用它们。 <code>from_param()</code> 类方法接收传递给函数调用的 Python 对象,它应该进行类型检查或任何需要以确保该对象是可接受的,然后返回对象本身,它的 <code>_as_parameter_</code>属性,或者在这种情况下您想作为 C 函数参数传递的任何内容。 同样,结果应该是整数、字符串、字节、[[#module-ctypes|ctypes]] 实例或具有 <code>_as_parameter_</code> 属性的对象。
to implement a <code>from_param()</code> class method for them to be able to use them
 
in the <code>argtypes</code> sequence. The <code>from_param()</code> class method receives
 
the Python object passed to the function call, it should do a typecheck or
 
whatever is needed to make sure this object is acceptable, and then return the
 
object itself, its <code>_as_parameter_</code> attribute, or whatever you want to
 
pass as the C function argument in this case. Again, the result should be an
 
integer, string, bytes, a [[#module-ctypes|<code>ctypes</code>]] instance, or an object with an
 
<code>_as_parameter_</code> attribute.
 
  
  
第618行: 第534行:
  
 
<span id="ctypes-return-types"></span>
 
<span id="ctypes-return-types"></span>
=== Return types ===
+
=== 返回类型 ===
  
By default functions are assumed to return the C <span class="xref c c-texpr">int</span> type. Other
+
默认情况下,函数假定返回 C <span class="xref c c-texpr">int</span> 类型。 其他返回类型可以通过设置函数对象的<code>restype</code>属性来指定。
return types can be specified by setting the <code>restype</code> attribute of the
 
function object.
 
  
Here is a more advanced example, it uses the <code>strchr</code> function, which expects
+
这是一个更高级的例子,它使用 <code>strchr</code> 函数,它需要一个字符串指针和一个字符,并返回一个指向字符串的指针:
a string pointer and a char, and returns a pointer to a string:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第631行: 第544行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; strchr = libc.strchr
+
<syntaxhighlight lang="python3">>>> strchr = libc.strchr
&gt;&gt;&gt; strchr(b&quot;abcdef&quot;, ord(&quot;d&quot;))   
+
>>> strchr(b"abcdef", ord("d"))   
 
8059983
 
8059983
&gt;&gt;&gt; strchr.restype = c_char_p    # c_char_p is a pointer to a string
+
>>> strchr.restype = c_char_p    # c_char_p is a pointer to a string
&gt;&gt;&gt; strchr(b&quot;abcdef&quot;, ord(&quot;d&quot;))
+
>>> strchr(b"abcdef", ord("d"))
 
b'def'
 
b'def'
&gt;&gt;&gt; print(strchr(b&quot;abcdef&quot;, ord(&quot;x&quot;)))
+
>>> print(strchr(b"abcdef", ord("x")))
 
None
 
None
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
If you want to avoid the <code>ord(&quot;x&quot;)</code> calls above, you can set the
+
如果要避免上面的 <code>ord(&quot;x&quot;)</code> 调用,可以设置 <code>argtypes</code> 属性,第二个参数将从单个字符的 Python 字节对象转换为 C 字符:
<code>argtypes</code> attribute, and the second argument will be converted from a
 
single character Python bytes object into a C char:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第652行: 第563行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; strchr.restype = c_char_p
+
<syntaxhighlight lang="python3">>>> strchr.restype = c_char_p
&gt;&gt;&gt; strchr.argtypes = [c_char_p, c_char]
+
>>> strchr.argtypes = [c_char_p, c_char]
&gt;&gt;&gt; strchr(b&quot;abcdef&quot;, b&quot;d&quot;)
+
>>> strchr(b"abcdef", b"d")
 
'def'
 
'def'
&gt;&gt;&gt; strchr(b&quot;abcdef&quot;, b&quot;def&quot;)
+
>>> strchr(b"abcdef", b"def")
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
 
ArgumentError: argument 2: exceptions.TypeError: one character string expected
 
ArgumentError: argument 2: exceptions.TypeError: one character string expected
&gt;&gt;&gt; print(strchr(b&quot;abcdef&quot;, b&quot;x&quot;))
+
>>> print(strchr(b"abcdef", b"x"))
 
None
 
None
&gt;&gt;&gt; strchr(b&quot;abcdef&quot;, b&quot;d&quot;)
+
>>> strchr(b"abcdef", b"d")
 
'def'
 
'def'
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
You can also use a callable Python object (a function or a class for example) as
+
如果外部函数返回整数,您还可以使用可调用的 Python 对象(例如函数或类)作为 <code>restype</code> 属性。 将使用 C 函数返回的 ''整数'' 调用可调用对象,并且此调用的结果将用作函数调用的结果。 这对于检查错误返回值并自动引发异常很有用:
the <code>restype</code> attribute, if the foreign function returns an integer. The
 
callable will be called with the ''integer'' the C function returns, and the
 
result of this call will be used as the result of your function call. This is
 
useful to check for error return values and automatically raise an exception:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第679行: 第586行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; GetModuleHandle = windll.kernel32.GetModuleHandleA   
+
<syntaxhighlight lang="python3">>>> GetModuleHandle = windll.kernel32.GetModuleHandleA   
&gt;&gt;&gt; def ValidHandle(value):
+
>>> def ValidHandle(value):
 
...    if value == 0:
 
...    if value == 0:
 
...        raise WinError()
 
...        raise WinError()
 
...    return value
 
...    return value
 
...
 
...
&gt;&gt;&gt;
+
>>>
&gt;&gt;&gt; GetModuleHandle.restype = ValidHandle   
+
>>> GetModuleHandle.restype = ValidHandle   
&gt;&gt;&gt; GetModuleHandle(None)   
+
>>> GetModuleHandle(None)   
 
486539264
 
486539264
&gt;&gt;&gt; GetModuleHandle(&quot;something silly&quot;)   
+
>>> GetModuleHandle("something silly")   
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
   File &quot;&lt;stdin&gt;&quot;, line 3, in ValidHandle
+
   File "<stdin>", line 3, in ValidHandle
 
OSError: [Errno 126] The specified module could not be found.
 
OSError: [Errno 126] The specified module could not be found.
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<code>WinError</code> is a function which will call Windows <code>FormatMessage()</code> api to
+
<code>WinError</code> 是一个函数,它将调用 Windows <code>FormatMessage()</code> api 来获取错误代码的字符串表示,而 ''返回'' 异常。 <code>WinError</code> 带有一个可选的错误代码参数,如果没有使用它,它会调用 [[#ctypes.GetLastError|GetLastError()]] 来检索它。
get the string representation of an error code, and ''returns'' an exception.
 
<code>WinError</code> takes an optional error code parameter, if no one is used, it calls
 
[[#ctypes.GetLastError|<code>GetLastError()</code>]] to retrieve it.
 
  
Please note that a much more powerful error checking mechanism is available
+
请注意,通过 <code>errcheck</code> 属性可以使用更强大的错误检查机制; 有关详细信息,请参阅参考手册。
through the <code>errcheck</code> attribute; see the reference manual for details.
 
  
  
第712行: 第615行:
  
 
<span id="ctypes-passing-pointers"></span>
 
<span id="ctypes-passing-pointers"></span>
=== Passing pointers (or: passing parameters by reference) ===
+
=== 传递指针(或:通过引用传递参数) ===
  
Sometimes a C api function expects a ''pointer'' to a data type as parameter,
+
有时一个 C api 函数需要一个指向数据类型的 ''指针'' 作为参数,可能是写入相应的位置,或者如果数据太大而无法通过值传递。 这也称为 ''通过引用'' 传递参数。
probably to write into the corresponding location, or if the data is too large
 
to be passed by value. This is also known as ''passing parameters by reference''.
 
  
[[#module-ctypes|<code>ctypes</code>]] exports the [[#ctypes.byref|<code>byref()</code>]] function which is used to pass parameters
+
[[#module-ctypes|ctypes]] 导出 [[#ctypes.byref|byref()]] 函数,用于通过引用传递参数。 使用[[#ctypes.pointer|pointer()]]函数也可以达到同样的效果,虽然[[#ctypes.pointer|pointer()]]做了很多工作,因为它构造了一个真正的指针对象,所以使用[[#ctypes.byref|速度更快]byref()]] 如果你不需要 Python 本身的指针对象:
by reference. The same effect can be achieved with the [[#ctypes.pointer|<code>pointer()</code>]] function,
 
although [[#ctypes.pointer|<code>pointer()</code>]] does a lot more work since it constructs a real pointer
 
object, so it is faster to use [[#ctypes.byref|<code>byref()</code>]] if you don't need the pointer
 
object in Python itself:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第728行: 第625行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; i = c_int()
+
<syntaxhighlight lang="python3">>>> i = c_int()
&gt;&gt;&gt; f = c_float()
+
>>> f = c_float()
&gt;&gt;&gt; s = create_string_buffer(b'\000' * 32)
+
>>> s = create_string_buffer(b'\000' * 32)
&gt;&gt;&gt; print(i.value, f.value, repr(s.value))
+
>>> print(i.value, f.value, repr(s.value))
 
0 0.0 b''
 
0 0.0 b''
&gt;&gt;&gt; libc.sscanf(b&quot;1 3.14 Hello&quot;, b&quot;%d %f %s&quot;,
+
>>> libc.sscanf(b"1 3.14 Hello", b"%d %f %s",
 
...            byref(i), byref(f), s)
 
...            byref(i), byref(f), s)
 
3
 
3
&gt;&gt;&gt; print(i.value, f.value, repr(s.value))
+
>>> print(i.value, f.value, repr(s.value))
 
1 3.1400001049 b'Hello'
 
1 3.1400001049 b'Hello'
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
第748行: 第645行:
  
 
<span id="ctypes-structures-unions"></span>
 
<span id="ctypes-structures-unions"></span>
=== Structures and unions ===
+
=== 结构和工会 ===
  
Structures and unions must derive from the [[#ctypes.Structure|<code>Structure</code>]] and [[#ctypes.Union|<code>Union</code>]]
+
结构和联合必须从 [[#module-ctypes|ctypes]] 模块中定义的 [[#ctypes.Structure|Structure]] [[#ctypes.Union|Union]] 基类派生。 每个子类必须定义一个 <code>_fields_</code> 属性。 <code>_fields_</code> 必须是 ''2 元组'' 的列表,包含 ''字段名称'' ''字段类型''
base classes which are defined in the [[#module-ctypes|<code>ctypes</code>]] module. Each subclass must
 
define a <code>_fields_</code> attribute. <code>_fields_</code> must be a list of
 
''2-tuples'', containing a ''field name'' and a ''field type''.
 
  
The field type must be a [[#module-ctypes|<code>ctypes</code>]] type like [[#ctypes.c_int|<code>c_int</code>]], or any other
+
字段类型必须是 [[#module-ctypes|ctypes]] 类型,如 [[#ctypes.c_int|c_int]],或任何其他派生的 [[#module-ctypes|ctypes]] 类型:结构、联合、数组、指针。
derived [[#module-ctypes|<code>ctypes</code>]] type: structure, union, array, pointer.
 
  
Here is a simple example of a POINT structure, which contains two integers named
+
下面是一个简单的 POINT 结构示例,其中包含两个名为 ''x'' ''y'' 的整数,并且还展示了如何在构造函数中初始化结构:
''x'' and ''y'', and also shows how to initialize a structure in the constructor:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第765行: 第657行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes import *
+
<syntaxhighlight lang="python3">>>> from ctypes import *
&gt;&gt;&gt; class POINT(Structure):
+
>>> class POINT(Structure):
...    _fields_ = [(&quot;x&quot;, c_int),
+
...    _fields_ = [("x", c_int),
...                (&quot;y&quot;, c_int)]
+
...                ("y", c_int)]
 
...
 
...
&gt;&gt;&gt; point = POINT(10, 20)
+
>>> point = POINT(10, 20)
&gt;&gt;&gt; print(point.x, point.y)
+
>>> print(point.x, point.y)
 
10 20
 
10 20
&gt;&gt;&gt; point = POINT(y=5)
+
>>> point = POINT(y=5)
&gt;&gt;&gt; print(point.x, point.y)
+
>>> print(point.x, point.y)
 
0 5
 
0 5
&gt;&gt;&gt; POINT(1, 2, 3)
+
>>> POINT(1, 2, 3)
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
 
TypeError: too many initializers
 
TypeError: too many initializers
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
You can, however, build much more complicated structures. A structure can
+
但是,您可以构建更复杂的结构。 通过将结构用作字段类型,结构本身可以包含其他结构。
itself contain other structures by using a structure as a field type.
 
  
Here is a RECT structure which contains two POINTs named ''upperleft'' and
+
这是一个 RECT 结构,它包含两个名为 ''upperleft'' ''lowerright'' 的 POINT:
''lowerright'':
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第795行: 第685行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; class RECT(Structure):
+
<syntaxhighlight lang="python3">>>> class RECT(Structure):
...    _fields_ = [(&quot;upperleft&quot;, POINT),
+
...    _fields_ = [("upperleft", POINT),
...                (&quot;lowerright&quot;, POINT)]
+
...                ("lowerright", POINT)]
 
...
 
...
&gt;&gt;&gt; rc = RECT(point)
+
>>> rc = RECT(point)
&gt;&gt;&gt; print(rc.upperleft.x, rc.upperleft.y)
+
>>> print(rc.upperleft.x, rc.upperleft.y)
 
0 5
 
0 5
&gt;&gt;&gt; print(rc.lowerright.x, rc.lowerright.y)
+
>>> print(rc.lowerright.x, rc.lowerright.y)
 
0 0
 
0 0
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Nested structures can also be initialized in the constructor in several ways:
+
嵌套结构也可以通过以下几种方式在构造函数中初始化:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第815行: 第705行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; r = RECT(POINT(1, 2), POINT(3, 4))
+
<syntaxhighlight lang="python3">>>> r = RECT(POINT(1, 2), POINT(3, 4))
&gt;&gt;&gt; r = RECT((1, 2), (3, 4))</pre>
+
>>> r = RECT((1, 2), (3, 4))</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Field [[../../glossary#term-descriptor|<span class="xref std std-term">descriptor</span>]]s can be retrieved from the ''class'', they are useful
+
字段 [[../../glossary#term-descriptor|描述符]] 可以从 '''' 中检索,它们对调试很有用,因为它们可以提供有用的信息:
for debugging because they can provide useful information:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第828行: 第717行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; print(POINT.x)
+
<syntaxhighlight lang="python3">>>> print(POINT.x)
&lt;Field type=c_long, ofs=0, size=4&gt;
+
<Field type=c_long, ofs=0, size=4>
&gt;&gt;&gt; print(POINT.y)
+
>>> print(POINT.y)
&lt;Field type=c_long, ofs=4, size=4&gt;
+
<Field type=c_long, ofs=4, size=4>
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
第841行: 第730行:
 
警告
 
警告
  
[[#module-ctypes|<code>ctypes</code>]] does not support passing unions or structures with bit-fields
+
[[#module-ctypes|ctypes]] 不支持将带有位域的联合或结构按值传递给函数。 虽然这可能适用于 32 位 x86,但库不保证在一般情况下工作。 具有位域的联合和结构应始终通过指针传递给函数。
to functions by value. While this may work on 32-bit x86, it's not
 
guaranteed by the library to work in the general case. Unions and
 
structures with bit-fields should always be passed to functions by pointer.
 
  
  
第852行: 第738行:
 
<div id="structure-union-alignment-and-byte-order" class="section">
 
<div id="structure-union-alignment-and-byte-order" class="section">
  
=== Structure/union alignment and byte order ===
+
=== 结构/联合对齐和字节顺序 ===
  
By default, Structure and Union fields are aligned in the same way the C
+
默认情况下,Structure 和 Union 字段的对齐方式与 C 编译器的对齐方式相同。 可以通过在子类定义中指定 <code>_pack_</code> 类属性来覆盖此行为。 这必须设置为正整数并指定字段的最大对齐方式。 这也是 <code>#pragma pack(n)</code> MSVC 中所做的。
compiler does it. It is possible to override this behavior by specifying a
 
<code>_pack_</code> class attribute in the subclass definition. This must be set to a
 
positive integer and specifies the maximum alignment for the fields. This is
 
what <code>#pragma pack(n)</code> also does in MSVC.
 
  
[[#module-ctypes|<code>ctypes</code>]] uses the native byte order for Structures and Unions. To build
+
[[#module-ctypes|ctypes]] 使用结构和联合的本机字节顺序。 要构建具有非本机字节顺序的结构,您可以使用 [[#ctypes.BigEndianStructure|BigEndianStructure]][[#ctypes.LittleEndianStructure|LittleEndianStructure]]<code>BigEndianUnion</code> <code>LittleEndianUnion</code> 基类之一。 这些类不能包含指针字段。
structures with non-native byte order, you can use one of the
 
[[#ctypes.BigEndianStructure|<code>BigEndianStructure</code>]], [[#ctypes.LittleEndianStructure|<code>LittleEndianStructure</code>]],
 
<code>BigEndianUnion</code>, and <code>LittleEndianUnion</code> base classes. These
 
classes cannot contain pointer fields.
 
  
  
第871行: 第749行:
  
 
<span id="ctypes-bit-fields-in-structures-unions"></span>
 
<span id="ctypes-bit-fields-in-structures-unions"></span>
=== Bit fields in structures and unions ===
+
=== 结构体和联合体中的位域 ===
  
It is possible to create structures and unions containing bit fields. Bit fields
+
可以创建包含位域的结构和联合。 位域仅适用于整数域,位宽被指定为 <code>_fields_</code> 元组中的第三项:
are only possible for integer fields, the bit width is specified as the third
 
item in the <code>_fields_</code> tuples:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第881行: 第757行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; class Int(Structure):
+
<syntaxhighlight lang="python3">>>> class Int(Structure):
...    _fields_ = [(&quot;first_16&quot;, c_int, 16),
+
...    _fields_ = [("first_16", c_int, 16),
...                (&quot;second_16&quot;, c_int, 16)]
+
...                ("second_16", c_int, 16)]
 
...
 
...
&gt;&gt;&gt; print(Int.first_16)
+
>>> print(Int.first_16)
&lt;Field type=c_long, ofs=0:0, bits=16&gt;
+
<Field type=c_long, ofs=0:0, bits=16>
&gt;&gt;&gt; print(Int.second_16)
+
>>> print(Int.second_16)
&lt;Field type=c_long, ofs=0:16, bits=16&gt;
+
<Field type=c_long, ofs=0:16, bits=16>
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
第899行: 第775行:
  
 
<span id="ctypes-arrays"></span>
 
<span id="ctypes-arrays"></span>
=== Arrays ===
+
=== 数组 ===
  
Arrays are sequences, containing a fixed number of instances of the same type.
+
数组是序列,包含固定数量的相同类型的实例。
  
The recommended way to create array types is by multiplying a data type with a
+
创建数组类型的推荐方法是将数据类型与正整数相乘:
positive integer:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第910行: 第785行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>TenPointsArrayType = POINT * 10</pre>
+
<syntaxhighlight lang="python3">TenPointsArrayType = POINT * 10</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Here is an example of a somewhat artificial data type, a structure containing 4
+
这是一个有点人为的数据类型的示例,该结构包含 4 个 POINT 以及其他内容:
POINTs among other stuff:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第922行: 第796行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes import *
+
<syntaxhighlight lang="python3">>>> from ctypes import *
&gt;&gt;&gt; class POINT(Structure):
+
>>> class POINT(Structure):
...    _fields_ = (&quot;x&quot;, c_int), (&quot;y&quot;, c_int)
+
...    _fields_ = ("x", c_int), ("y", c_int)
 
...
 
...
&gt;&gt;&gt; class MyStruct(Structure):
+
>>> class MyStruct(Structure):
...    _fields_ = [(&quot;a&quot;, c_int),
+
...    _fields_ = [("a", c_int),
...                (&quot;b&quot;, c_float),
+
...                ("b", c_float),
...                (&quot;point_array&quot;, POINT * 4)]
+
...                ("point_array", POINT * 4)]
&gt;&gt;&gt;
+
>>>
&gt;&gt;&gt; print(len(MyStruct().point_array))
+
>>> print(len(MyStruct().point_array))
 
4
 
4
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Instances are created in the usual way, by calling the class:
+
实例以通常的方式创建,通过调用类:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第944行: 第818行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>arr = TenPointsArrayType()
+
<syntaxhighlight lang="python3">arr = TenPointsArrayType()
 
for pt in arr:
 
for pt in arr:
     print(pt.x, pt.y)</pre>
+
     print(pt.x, pt.y)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The above code print a series of <code>0 0</code> lines, because the array contents is
+
上面的代码打印了一系列 <code>0 0</code> 行,因为数组内容被初始化为零。
initialized to zeros.
 
  
Initializers of the correct type can also be specified:
+
还可以指定正确类型的初始化程序:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第960行: 第833行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes import *
+
<syntaxhighlight lang="python3">>>> from ctypes import *
&gt;&gt;&gt; TenIntegers = c_int * 10
+
>>> TenIntegers = c_int * 10
&gt;&gt;&gt; ii = TenIntegers(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+
>>> ii = TenIntegers(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
&gt;&gt;&gt; print(ii)
+
>>> print(ii)
&lt;c_long_Array_10 object at 0x...&gt;
+
<c_long_Array_10 object at 0x...>
&gt;&gt;&gt; for i in ii: print(i, end=&quot; &quot;)
+
>>> for i in ii: print(i, end=" ")
 
...
 
...
 
1 2 3 4 5 6 7 8 9 10
 
1 2 3 4 5 6 7 8 9 10
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
第978行: 第851行:
  
 
<span id="ctypes-pointers"></span>
 
<span id="ctypes-pointers"></span>
=== Pointers ===
+
=== 指针 ===
  
Pointer instances are created by calling the [[#ctypes.pointer|<code>pointer()</code>]] function on a
+
指针实例是通过在 [[#module-ctypes|ctypes]] 类型上调用 [[#ctypes.pointer|pointer()]] 函数来创建的:
[[#module-ctypes|<code>ctypes</code>]] type:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第987行: 第859行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes import *
+
<syntaxhighlight lang="python3">>>> from ctypes import *
&gt;&gt;&gt; i = c_int(42)
+
>>> i = c_int(42)
&gt;&gt;&gt; pi = pointer(i)
+
>>> pi = pointer(i)
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Pointer instances have a [[#ctypes._Pointer.contents|<code>contents</code>]] attribute which
+
指针实例有一个 [[#ctypes._Pointer.contents|contents]] 属性,它返回指针指向的对象,上面的 <code>i</code> 对象:
returns the object to which the pointer points, the <code>i</code> object above:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,002行: 第873行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; pi.contents
+
<syntaxhighlight lang="python3">>>> pi.contents
 
c_long(42)
 
c_long(42)
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Note that [[#module-ctypes|<code>ctypes</code>]] does not have OOR (original object return), it constructs a
+
请注意, [[#module-ctypes|ctypes]] 没有 OOR(原始对象返回),每次检索属性时它都会构造一个新的等效对象:
new, equivalent object each time you retrieve an attribute:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,016行: 第886行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; pi.contents is i
+
<syntaxhighlight lang="python3">>>> pi.contents is i
 
False
 
False
&gt;&gt;&gt; pi.contents is pi.contents
+
>>> pi.contents is pi.contents
 
False
 
False
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Assigning another [[#ctypes.c_int|<code>c_int</code>]] instance to the pointer's contents attribute
+
将另一个 [[#ctypes.c_int|c_int]] 实例分配给指针的内容属性会导致指针指向存储它的内存位置:
would cause the pointer to point to the memory location where this is stored:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,032行: 第901行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; i = c_int(99)
+
<syntaxhighlight lang="python3">>>> i = c_int(99)
&gt;&gt;&gt; pi.contents = i
+
>>> pi.contents = i
&gt;&gt;&gt; pi.contents
+
>>> pi.contents
 
c_long(99)
 
c_long(99)
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Pointer instances can also be indexed with integers:
+
指针实例也可以用整数索引:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,047行: 第916行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; pi[0]
+
<syntaxhighlight lang="python3">>>> pi[0]
 
99
 
99
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Assigning to an integer index changes the pointed to value:
+
分配给整数索引会更改指向的值:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,060行: 第929行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; print(i)
+
<syntaxhighlight lang="python3">>>> print(i)
 
c_long(99)
 
c_long(99)
&gt;&gt;&gt; pi[0] = 22
+
>>> pi[0] = 22
&gt;&gt;&gt; print(i)
+
>>> print(i)
 
c_long(22)
 
c_long(22)
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
It is also possible to use indexes different from 0, but you must know what
+
也可以使用不同于 0 的索引,但您必须知道自己在做什么,就像在 C 中一样:您可以访问或更改任意内存位置。 通常,如果您从 C 函数接收指针,并且您 ''知道'' 该指针实际上指向一个数组而不是单个项目,则您只会使用此功能。
you're doing, just as in C: You can access or change arbitrary memory locations.
 
Generally you only use this feature if you receive a pointer from a C function,
 
and you ''know'' that the pointer actually points to an array instead of a single
 
item.
 
  
Behind the scenes, the [[#ctypes.pointer|<code>pointer()</code>]] function does more than simply create
+
在幕后,[[#ctypes.pointer|pointer()]] 函数不仅仅是创建指针实例,它还必须首先创建指针 ''types''。 这是通过 [[#ctypes.POINTER|POINTER()]] 函数完成的,该函数接受任何 [[#module-ctypes|ctypes]] 类型,并返回一个新类型:
pointer instances, it has to create pointer ''types'' first. This is done with the
 
[[#ctypes.POINTER|<code>POINTER()</code>]] function, which accepts any [[#module-ctypes|<code>ctypes</code>]] type, and returns a
 
new type:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,085行: 第947行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; PI = POINTER(c_int)
+
<syntaxhighlight lang="python3">>>> PI = POINTER(c_int)
&gt;&gt;&gt; PI
+
>>> PI
&lt;class 'ctypes.LP_c_long'&gt;
+
<class 'ctypes.LP_c_long'>
&gt;&gt;&gt; PI(42)
+
>>> PI(42)
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
 
TypeError: expected c_long instead of int
 
TypeError: expected c_long instead of int
&gt;&gt;&gt; PI(c_int(42))
+
>>> PI(c_int(42))
&lt;ctypes.LP_c_long object at 0x...&gt;
+
<ctypes.LP_c_long object at 0x...>
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Calling the pointer type without an argument creates a <code>NULL</code> pointer.
+
不带参数调用指针类型会创建一个 <code>NULL</code> 指针。 <code>NULL</code> 指针有一个 <code>False</code> 布尔值:
<code>NULL</code> pointers have a <code>False</code> boolean value:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,106行: 第967行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; null_ptr = POINTER(c_int)()
+
<syntaxhighlight lang="python3">>>> null_ptr = POINTER(c_int)()
&gt;&gt;&gt; print(bool(null_ptr))
+
>>> print(bool(null_ptr))
 
False
 
False
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
[[#module-ctypes|<code>ctypes</code>]] checks for <code>NULL</code> when dereferencing pointers (but dereferencing
+
[[#module-ctypes|ctypes]] 在解引用指针时检查 <code>NULL</code>(但解引用无效的非 <code>NULL</code> 指针会使 Python 崩溃):
invalid non-<code>NULL</code> pointers would crash Python):
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,121行: 第981行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; null_ptr[0]
+
<syntaxhighlight lang="python3">>>> null_ptr[0]
 
Traceback (most recent call last):
 
Traceback (most recent call last):
 
     ....
 
     ....
 
ValueError: NULL pointer access
 
ValueError: NULL pointer access
&gt;&gt;&gt;
+
>>>
  
&gt;&gt;&gt; null_ptr[0] = 1234
+
>>> null_ptr[0] = 1234
 
Traceback (most recent call last):
 
Traceback (most recent call last):
 
     ....
 
     ....
 
ValueError: NULL pointer access
 
ValueError: NULL pointer access
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
第1,141行: 第1,001行:
  
 
<span id="ctypes-type-conversions"></span>
 
<span id="ctypes-type-conversions"></span>
=== Type conversions ===
+
=== 类型转换 ===
  
Usually, ctypes does strict type checking. This means, if you have
+
通常,ctypes 会进行严格的类型检查。 这意味着,如果在函数的 <code>argtypes</code> 列表中有 <code>POINTER(c_int)</code> 或作为结构定义中成员字段的类型,则只接受完全相同类型的实例。 此规则有一些例外,其中 ctypes 接受其他对象。 例如,您可以传递兼容的数组实例而不是指针类型。 因此,对于 <code>POINTER(c_int)</code>,ctypes 接受一个 c_int 数组:
<code>POINTER(c_int)</code> in the <code>argtypes</code> list of a function or as the type of
 
a member field in a structure definition, only instances of exactly the same
 
type are accepted. There are some exceptions to this rule, where ctypes accepts
 
other objects. For example, you can pass compatible array instances instead of
 
pointer types. So, for <code>POINTER(c_int)</code>, ctypes accepts an array of c_int:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,154行: 第1,009行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; class Bar(Structure):
+
<syntaxhighlight lang="python3">>>> class Bar(Structure):
...    _fields_ = [(&quot;count&quot;, c_int), (&quot;values&quot;, POINTER(c_int))]
+
...    _fields_ = [("count", c_int), ("values", POINTER(c_int))]
 
...
 
...
&gt;&gt;&gt; bar = Bar()
+
>>> bar = Bar()
&gt;&gt;&gt; bar.values = (c_int * 3)(1, 2, 3)
+
>>> bar.values = (c_int * 3)(1, 2, 3)
&gt;&gt;&gt; bar.count = 3
+
>>> bar.count = 3
&gt;&gt;&gt; for i in range(bar.count):
+
>>> for i in range(bar.count):
 
...    print(bar.values[i])
 
...    print(bar.values[i])
 
...
 
...
第1,166行: 第1,021行:
 
2
 
2
 
3
 
3
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
In addition, if a function argument is explicitly declared to be a pointer type
+
此外,如果函数参数在 <code>argtypes</code> 中显式声明为指针类型(例如 <code>POINTER(c_int)</code>),则为指向类型的对象(在本例中为 <code>c_int</code>)可以传递给函数。 在这种情况下,ctypes 将自动应用所需的 [[#ctypes.byref|byref()]] 转换。
(such as <code>POINTER(c_int)</code>) in <code>argtypes</code>, an object of the pointed
 
type (<code>c_int</code> in this case) can be passed to the function. ctypes will apply
 
the required [[#ctypes.byref|<code>byref()</code>]] conversion in this case automatically.
 
  
To set a POINTER type field to <code>NULL</code>, you can assign <code>None</code>:
+
要将 POINTER 类型字段设置为 <code>NULL</code>,您可以分配 <code>None</code>
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,182行: 第1,034行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; bar.values = None
+
<syntaxhighlight lang="python3">>>> bar.values = None
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Sometimes you have instances of incompatible types. In C, you can cast one type
+
有时您有不兼容类型的实例。 在 C 中,您可以将一种类型转换为另一种类型。 [[#module-ctypes|ctypes]] 提供了一个 [[#ctypes.cast|cast()]] 函数,可以以同样的方式使用。 上面定义的 <code>Bar</code> 结构接受 <code>POINTER(c_int)</code> 指针或 [[#ctypes.c_int|c_int]] 数组作为其 <code>values</code> 字段,但不接受其他类型的实例:
into another type. [[#module-ctypes|<code>ctypes</code>]] provides a [[#ctypes.cast|<code>cast()</code>]] function which can be
 
used in the same way. The <code>Bar</code> structure defined above accepts
 
<code>POINTER(c_int)</code> pointers or [[#ctypes.c_int|<code>c_int</code>]] arrays for its <code>values</code> field,
 
but not instances of other types:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,198行: 第1,046行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; bar.values = (c_byte * 4)()
+
<syntaxhighlight lang="python3">>>> bar.values = (c_byte * 4)()
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
 
TypeError: incompatible types, c_byte_Array_4 instance instead of LP_c_long instance
 
TypeError: incompatible types, c_byte_Array_4 instance instead of LP_c_long instance
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
For these cases, the [[#ctypes.cast|<code>cast()</code>]] function is handy.
+
对于这些情况,[[#ctypes.cast|cast()]] 函数很方便。
  
The [[#ctypes.cast|<code>cast()</code>]] function can be used to cast a ctypes instance into a pointer
+
[[#ctypes.cast|cast()]] 函数可用于将 ctypes 实例转换为指向不同 ctypes 数据类型的指针。 [[#ctypes.cast|cast()]] 接受两个参数,一个是或可以转换为某种指针的 ctypes 对象,以及一个 ctypes 指针类型。 它返回第二个参数的实例,它引用与第一个参数相同的内存块:
to a different ctypes data type. [[#ctypes.cast|<code>cast()</code>]] takes two parameters, a ctypes
 
object that is or can be converted to a pointer of some kind, and a ctypes
 
pointer type. It returns an instance of the second argument, which references
 
the same memory block as the first argument:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,219行: 第1,063行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; a = (c_byte * 4)()
+
<syntaxhighlight lang="python3">>>> a = (c_byte * 4)()
&gt;&gt;&gt; cast(a, POINTER(c_int))
+
>>> cast(a, POINTER(c_int))
&lt;ctypes.LP_c_long object at ...&gt;
+
<ctypes.LP_c_long object at ...>
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
So, [[#ctypes.cast|<code>cast()</code>]] can be used to assign to the <code>values</code> field of <code>Bar</code> the
+
因此,可以使用 [[#ctypes.cast|cast()]] 将结构体分配给 <code>Bar</code> <code>values</code> 字段:
structure:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,234行: 第1,077行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; bar = Bar()
+
<syntaxhighlight lang="python3">>>> bar = Bar()
&gt;&gt;&gt; bar.values = cast((c_byte * 4)(), POINTER(c_int))
+
>>> bar.values = cast((c_byte * 4)(), POINTER(c_int))
&gt;&gt;&gt; print(bar.values[0])
+
>>> print(bar.values[0])
 
0
 
0
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
第1,248行: 第1,091行:
  
 
<span id="ctypes-incomplete-types"></span>
 
<span id="ctypes-incomplete-types"></span>
=== Incomplete Types ===
+
=== 不完全类型 ===
  
''Incomplete Types'' are structures, unions or arrays whose members are not yet
+
''不完整类型'' 是结构、联合或数组,其成员尚未指定。 在 C 中,它们由前向声明指定,稍后定义:
specified. In C, they are specified by forward declarations, which are defined
 
later:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,258行: 第1,099行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>struct cell; /* forward declaration */
+
<syntaxhighlight lang="python3">struct cell; /* forward declaration */
  
 
struct cell {
 
struct cell {
 
     char *name;
 
     char *name;
 
     struct cell *next;
 
     struct cell *next;
};</pre>
+
};</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The straightforward translation into ctypes code would be this, but it does not
+
直接转换为 ctypes 代码是这样的,但它不起作用:
work:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,275行: 第1,115行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; class cell(Structure):
+
<syntaxhighlight lang="python3">>>> class cell(Structure):
...    _fields_ = [(&quot;name&quot;, c_char_p),
+
...    _fields_ = [("name", c_char_p),
...                (&quot;next&quot;, POINTER(cell))]
+
...                ("next", POINTER(cell))]
 
...
 
...
 
Traceback (most recent call last):
 
Traceback (most recent call last):
   File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
+
   File "<stdin>", line 1, in <module>
   File &quot;&lt;stdin&gt;&quot;, line 2, in cell
+
   File "<stdin>", line 2, in cell
 
NameError: name 'cell' is not defined
 
NameError: name 'cell' is not defined
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
because the new <code>class cell</code> is not available in the class statement itself.
+
因为新的 <code>class cell</code> class 语句本身中不可用。 在 [[#module-ctypes|ctypes]] 中,我们可以定义 <code>cell</code> 类,然后在 class 语句之后设置 <code>_fields_</code> 属性:
In [[#module-ctypes|<code>ctypes</code>]], we can define the <code>cell</code> class and set the <code>_fields_</code>
 
attribute later, after the class statement:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,296行: 第1,134行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes import *
+
<syntaxhighlight lang="python3">>>> from ctypes import *
&gt;&gt;&gt; class cell(Structure):
+
>>> class cell(Structure):
 
...    pass
 
...    pass
 
...
 
...
&gt;&gt;&gt; cell._fields_ = [(&quot;name&quot;, c_char_p),
+
>>> cell._fields_ = [("name", c_char_p),
...                  (&quot;next&quot;, POINTER(cell))]
+
...                  ("next", POINTER(cell))]
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Let's try it. We create two instances of <code>cell</code>, and let them point to each
+
让我们试试吧。 我们创建了两个 <code>cell</code> 的实例,并让它们相互指向,最后沿着指针链走几次:
other, and finally follow the pointer chain a few times:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,314行: 第1,151行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; c1 = cell()
+
<syntaxhighlight lang="python3">>>> c1 = cell()
&gt;&gt;&gt; c1.name = &quot;foo&quot;
+
>>> c1.name = b"foo"
&gt;&gt;&gt; c2 = cell()
+
>>> c2 = cell()
&gt;&gt;&gt; c2.name = &quot;bar&quot;
+
>>> c2.name = b"bar"
&gt;&gt;&gt; c1.next = pointer(c2)
+
>>> c1.next = pointer(c2)
&gt;&gt;&gt; c2.next = pointer(c1)
+
>>> c2.next = pointer(c1)
&gt;&gt;&gt; p = c1
+
>>> p = c1
&gt;&gt;&gt; for i in range(8):
+
>>> for i in range(8):
...    print(p.name, end=&quot; &quot;)
+
...    print(p.name, end=" ")
 
...    p = p.next[0]
 
...    p = p.next[0]
 
...
 
...
 
foo bar foo bar foo bar foo bar
 
foo bar foo bar foo bar foo bar
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
第1,336行: 第1,173行:
  
 
<span id="ctypes-callback-functions"></span>
 
<span id="ctypes-callback-functions"></span>
=== Callback functions ===
+
=== 回调函数 ===
  
[[#module-ctypes|<code>ctypes</code>]] allows creating C callable function pointers from Python callables.
+
[[#module-ctypes|ctypes]] 允许从 Python 可调用对象创建 C 可调用函数指针。 这些有时称为 ''回调函数''
These are sometimes called ''callback functions''.
 
  
First, you must create a class for the callback function. The class knows the
+
首先,您必须为回调函数创建一个类。 该类知道调用约定、返回类型以及此函数将接收的参数的数量和类型。
calling convention, the return type, and the number and types of arguments this
 
function will receive.
 
  
The [[#ctypes.CFUNCTYPE|<code>CFUNCTYPE()</code>]] factory function creates types for callback functions
+
[[#ctypes.CFUNCTYPE|CFUNCTYPE()]] 工厂函数使用 <code>cdecl</code> 调用约定为回调函数创建类型。 在 Windows 上,[[#ctypes.WINFUNCTYPE|WINFUNCTYPE()]] 工厂函数使用 <code>stdcall</code> 调用约定为回调函数创建类型。
using the <code>cdecl</code> calling convention. On Windows, the [[#ctypes.WINFUNCTYPE|<code>WINFUNCTYPE()</code>]]
 
factory function creates types for callback functions using the <code>stdcall</code>
 
calling convention.
 
  
Both of these factory functions are called with the result type as first
+
这两个工厂函数都以结果类型作为第一个参数被调用,回调函数期望的参数类型作为剩余的参数。
argument, and the callback functions expected argument types as the remaining
 
arguments.
 
  
I will present an example here which uses the standard C library's
+
我将在此处展示一个示例,该示例使用标准 C 库的 <code>qsort()</code> 函数,该函数用于在回调函数的帮助下对项目进行排序。 <code>qsort()</code> 将用于对整数数组进行排序:
<code>qsort()</code> function, that is used to sort items with the help of a callback
 
function. <code>qsort()</code> will be used to sort an array of integers:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,362行: 第1,189行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; IntArray5 = c_int * 5
+
<syntaxhighlight lang="python3">>>> IntArray5 = c_int * 5
&gt;&gt;&gt; ia = IntArray5(5, 1, 7, 33, 99)
+
>>> ia = IntArray5(5, 1, 7, 33, 99)
&gt;&gt;&gt; qsort = libc.qsort
+
>>> qsort = libc.qsort
&gt;&gt;&gt; qsort.restype = None
+
>>> qsort.restype = None
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<code>qsort()</code> must be called with a pointer to the data to sort, the number of
+
<code>qsort()</code> 必须使用指向要排序的数据的指针、数据数组中的项数、一项的大小以及指向比较函数、回调的指针来调用。 然后将使用两个指向项目的指针调用回调,如果第一个项目小于第二个项目,则它必须返回一个负整数,如果它们相等,则返回零,否则返回一个正整数。
items in the data array, the size of one item, and a pointer to the comparison
 
function, the callback. The callback will then be called with two pointers to
 
items, and it must return a negative integer if the first item is smaller than
 
the second, a zero if they are equal, and a positive integer otherwise.
 
  
So our callback function receives pointers to integers, and must return an
+
所以我们的回调函数接收指向整数的指针,并且必须返回一个整数。 首先我们为回调函数创建<code>type</code>
integer. First we create the <code>type</code> for the callback function:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,384行: 第1,206行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
+
<syntaxhighlight lang="python3">>>> CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
To get started, here is a simple callback that shows the values it gets
+
首先,这是一个简单的回调,显示它传递的值:
passed:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,397行: 第1,218行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; def py_cmp_func(a, b):
+
<syntaxhighlight lang="python3">>>> def py_cmp_func(a, b):
...    print(&quot;py_cmp_func&quot;, a[0], b[0])
+
...    print("py_cmp_func", a[0], b[0])
 
...    return 0
 
...    return 0
 
...
 
...
&gt;&gt;&gt; cmp_func = CMPFUNC(py_cmp_func)
+
>>> cmp_func = CMPFUNC(py_cmp_func)
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The result:
+
结果:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,413行: 第1,234行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; qsort(ia, len(ia), sizeof(c_int), cmp_func)   
+
<syntaxhighlight lang="python3">>>> qsort(ia, len(ia), sizeof(c_int), cmp_func)   
 
py_cmp_func 5 1
 
py_cmp_func 5 1
 
py_cmp_func 33 99
 
py_cmp_func 33 99
第1,419行: 第1,240行:
 
py_cmp_func 5 7
 
py_cmp_func 5 7
 
py_cmp_func 1 7
 
py_cmp_func 1 7
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Now we can actually compare the two items and return a useful result:
+
现在我们可以实际比较这两个项目并返回一个有用的结果:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,430行: 第1,251行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; def py_cmp_func(a, b):
+
<syntaxhighlight lang="python3">>>> def py_cmp_func(a, b):
...    print(&quot;py_cmp_func&quot;, a[0], b[0])
+
...    print("py_cmp_func", a[0], b[0])
 
...    return a[0] - b[0]
 
...    return a[0] - b[0]
 
...
 
...
&gt;&gt;&gt;
+
>>>
&gt;&gt;&gt; qsort(ia, len(ia), sizeof(c_int), CMPFUNC(py_cmp_func))  
+
>>> qsort(ia, len(ia), sizeof(c_int), CMPFUNC(py_cmp_func))  
 
py_cmp_func 5 1
 
py_cmp_func 5 1
 
py_cmp_func 33 99
 
py_cmp_func 33 99
第1,441行: 第1,262行:
 
py_cmp_func 1 7
 
py_cmp_func 1 7
 
py_cmp_func 5 7
 
py_cmp_func 5 7
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
As we can easily check, our array is sorted now:
+
正如我们可以轻松检查的那样,我们的数组现在已排序:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,452行: 第1,273行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; for i in ia: print(i, end=&quot; &quot;)
+
<syntaxhighlight lang="python3">>>> for i in ia: print(i, end=" ")
 
...
 
...
 
1 5 7 33 99
 
1 5 7 33 99
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The function factories can be used as decorator factories, so we may as well
+
函数工厂可以用作装饰器工厂,所以我们不妨这样写:
write:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,467行: 第1,287行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; @CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
+
<syntaxhighlight lang="python3">>>> @CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
 
... def py_cmp_func(a, b):
 
... def py_cmp_func(a, b):
...    print(&quot;py_cmp_func&quot;, a[0], b[0])
+
...    print("py_cmp_func", a[0], b[0])
 
...    return a[0] - b[0]
 
...    return a[0] - b[0]
 
...
 
...
&gt;&gt;&gt; qsort(ia, len(ia), sizeof(c_int), py_cmp_func)
+
>>> qsort(ia, len(ia), sizeof(c_int), py_cmp_func)
 
py_cmp_func 5 1
 
py_cmp_func 5 1
 
py_cmp_func 33 99
 
py_cmp_func 33 99
第1,478行: 第1,298行:
 
py_cmp_func 1 7
 
py_cmp_func 1 7
 
py_cmp_func 5 7
 
py_cmp_func 5 7
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
第1,485行: 第1,305行:
 
<div class="admonition note">
 
<div class="admonition note">
  
注解
+
笔记
  
Make sure you keep references to [[#ctypes.CFUNCTYPE|<code>CFUNCTYPE()</code>]] objects as long as they
+
确保保留对 [[#ctypes.CFUNCTYPE|CFUNCTYPE()]] 对象的引用,只要它们从 C 代码中使用即可。 [[#module-ctypes|ctypes]] 没有,如果你不这样做,它们可能会被垃圾收集,在进行回调时使你的程序崩溃。
are used from C code. [[#module-ctypes|<code>ctypes</code>]] doesn't, and if you don't, they may be
 
garbage collected, crashing your program when a callback is made.
 
  
Also, note that if the callback function is called in a thread created
+
另外,请注意,如果在 Python 控制之外创建的线程中调用回调函数(例如 通过调用回调的外部代码),ctypes 在每次调用时创建一个新的虚拟 Python 线程。 这种行为在大多数情况下是正确的,但这意味着使用 [[../threading#threading|threading.local]] 存储的值将 ''not'' 在不同的回调中存活,即使这些调用来自同一个 C 线程。
outside of Python's control (e.g. by the foreign code that calls the
 
callback), ctypes creates a new dummy Python thread on every invocation. This
 
behavior is correct for most purposes, but it means that values stored with
 
[[../threading#threading|<code>threading.local</code>]] will ''not'' survive across different callbacks, even when
 
those calls are made from the same C thread.
 
  
  
第1,505行: 第1,318行:
  
 
<span id="ctypes-accessing-values-exported-from-dlls"></span>
 
<span id="ctypes-accessing-values-exported-from-dlls"></span>
=== Accessing values exported from dlls ===
+
=== 访问从 dll 导出的值 ===
  
Some shared libraries not only export functions, they also export variables. An
+
一些共享库不仅导出函数,还导出变量。 Python 库本身中的一个示例是 [[../../c-api/init#c|Py_OptimizeFlag]],一个整数设置为 0、1 或 2,具体取决于给定的 [[../../using/cmdline#cmdoption-O|-O]] [[../../using/cmdline#cmdoption-OO|-OO]] 标志在启动时。
example in the Python library itself is the [[../../c-api/init#c|<code>Py_OptimizeFlag</code>]], an integer
 
set to 0, 1, or 2, depending on the [[../../using/cmdline#cmdoption-O|<code>-O</code>]] or [[../../using/cmdline#cmdoption-OO|<code>-OO</code>]] flag given on
 
startup.
 
  
[[#module-ctypes|<code>ctypes</code>]] can access values like this with the <code>in_dll()</code> class methods of
+
[[#module-ctypes|ctypes]] 可以使用该类型的 <code>in_dll()</code> 类方法访问这样的值。 ''pythonapi'' 是一个预定义的符号,可以访问 Python C api:
the type. ''pythonapi'' is a predefined symbol giving access to the Python C
 
api:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,520行: 第1,328行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; opt_flag = c_int.in_dll(pythonapi, &quot;Py_OptimizeFlag&quot;)
+
<syntaxhighlight lang="python3">>>> opt_flag = c_int.in_dll(pythonapi, "Py_OptimizeFlag")
&gt;&gt;&gt; print(opt_flag)
+
>>> print(opt_flag)
 
c_long(0)
 
c_long(0)
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
If the interpreter would have been started with [[../../using/cmdline#cmdoption-O|<code>-O</code>]], the sample would
+
如果解释器以 [[../../using/cmdline#cmdoption-O|-O]] 开始,则样本将打印 <code>c_long(1)</code>,或 <code>c_long(2)</code> 如果已指定 [[../../using/cmdline#cmdoption-OO|-OO]]
have printed <code>c_long(1)</code>, or <code>c_long(2)</code> if [[../../using/cmdline#cmdoption-OO|<code>-OO</code>]] would have been
 
specified.
 
  
An extended example which also demonstrates the use of pointers accesses the
+
一个扩展示例也演示了如何使用指针访问 Python 导出的 [[../../c-api/import#c|PyImport_FrozenModules]] 指针。
[[../../c-api/import#c|<code>PyImport_FrozenModules</code>]] pointer exported by Python.
 
  
Quoting the docs for that value:
+
引用该值的文档:
  
 
<blockquote><div>
 
<blockquote><div>
  
This pointer is initialized to point to an array of <span class="xref c c-texpr">''struct'' [[../../c-api/import#c|_frozen]]</span>
+
这个指针被初始化为指向一个 <span class="xref c c-texpr">struct _frozen</span> 记录数组,由一个成员都是 <code>NULL</code> 或零的记录终止。 导入冻结模块时,将在此表中搜索。 第三方代码可以利用此技巧来提供动态创建的冻结模块集合。
records, terminated by one whose members are all <code>NULL</code> or zero. When a frozen
 
module is imported, it is searched in this table. Third-party code could play
 
tricks with this to provide a dynamically created collection of frozen modules.
 
  
  
 
</div></blockquote>
 
</div></blockquote>
So manipulating this pointer could even prove useful. To restrict the example
+
所以操纵这个指针甚至可以证明是有用的。 为了限制示例大小,我们仅展示如何使用 [[#module-ctypes|ctypes]] 读取此表:
size, we show only how this table can be read with [[#module-ctypes|<code>ctypes</code>]]:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,553行: 第1,354行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes import *
+
<syntaxhighlight lang="python3">>>> from ctypes import *
&gt;&gt;&gt;
+
>>>
&gt;&gt;&gt; class struct_frozen(Structure):
+
>>> class struct_frozen(Structure):
...    _fields_ = [(&quot;name&quot;, c_char_p),
+
...    _fields_ = [("name", c_char_p),
...                (&quot;code&quot;, POINTER(c_ubyte)),
+
...                ("code", POINTER(c_ubyte)),
...                (&quot;size&quot;, c_int)]
+
...                ("size", c_int)]
 
...
 
...
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
We have defined the <span class="xref c c-texpr">''struct'' [[../../c-api/import#c|_frozen]]</span> data type, so we can get the pointer
+
我们已经定义了 <span class="xref c c-texpr">struct _frozen</span> 数据类型,所以我们可以得到指向表的指针:
to the table:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,572行: 第1,372行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; FrozenTable = POINTER(struct_frozen)
+
<syntaxhighlight lang="python3">>>> FrozenTable = POINTER(struct_frozen)
&gt;&gt;&gt; table = FrozenTable.in_dll(pythonapi, &quot;PyImport_FrozenModules&quot;)
+
>>> table = FrozenTable.in_dll(pythonapi, "PyImport_FrozenModules")
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Since <code>table</code> is a <code>pointer</code> to the array of <code>struct_frozen</code> records, we
+
由于 <code>table</code> <code>struct_frozen</code> 记录数组的 <code>pointer</code>,我们可以迭代它,但我们只需要确保我们的循环终止,因为指针没有大小. 迟早它可能会因访问冲突或其他原因而崩溃,因此最好在我们点击 <code>NULL</code> 条目时跳出循环:
can iterate over it, but we just have to make sure that our loop terminates,
 
because pointers have no size. Sooner or later it would probably crash with an
 
access violation or whatever, so it's better to break out of the loop when we
 
hit the <code>NULL</code> entry:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,589行: 第1,385行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; for item in table:
+
<syntaxhighlight lang="python3">>>> for item in table:
 
...    if item.name is None:
 
...    if item.name is None:
 
...        break
 
...        break
...    print(item.name.decode(&quot;ascii&quot;), item.size)
+
...    print(item.name.decode("ascii"), item.size)
 
...
 
...
 
_frozen_importlib 31764
 
_frozen_importlib 31764
第1,599行: 第1,395行:
 
__phello__ -161
 
__phello__ -161
 
__phello__.spam 161
 
__phello__.spam 161
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The fact that standard Python has a frozen module and a frozen package
+
标准 Python 有一个冻结模块和一个冻结包(由负的 <code>size</code> 成员表示)这一事实并不为人所知,它仅用于测试。 例如,尝试使用 <code>import __hello__</code>
(indicated by the negative <code>size</code> member) is not well known, it is only used
 
for testing. Try it out with <code>import __hello__</code> for example.
 
  
  
第1,613行: 第1,407行:
  
 
<span id="ctypes-surprises"></span>
 
<span id="ctypes-surprises"></span>
=== Surprises ===
+
=== 惊喜 ===
  
There are some edges in [[#module-ctypes|<code>ctypes</code>]] where you might expect something other
+
[[#module-ctypes|ctypes]] 中有一些边缘,你可能会期待一些与实际发生的情况不同的东西。
than what actually happens.
 
  
Consider the following example:
+
考虑以下示例:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,624行: 第1,417行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes import *
+
<syntaxhighlight lang="python3">>>> from ctypes import *
&gt;&gt;&gt; class POINT(Structure):
+
>>> class POINT(Structure):
...    _fields_ = (&quot;x&quot;, c_int), (&quot;y&quot;, c_int)
+
...    _fields_ = ("x", c_int), ("y", c_int)
 
...
 
...
&gt;&gt;&gt; class RECT(Structure):
+
>>> class RECT(Structure):
...    _fields_ = (&quot;a&quot;, POINT), (&quot;b&quot;, POINT)
+
...    _fields_ = ("a", POINT), ("b", POINT)
 
...
 
...
&gt;&gt;&gt; p1 = POINT(1, 2)
+
>>> p1 = POINT(1, 2)
&gt;&gt;&gt; p2 = POINT(3, 4)
+
>>> p2 = POINT(3, 4)
&gt;&gt;&gt; rc = RECT(p1, p2)
+
>>> rc = RECT(p1, p2)
&gt;&gt;&gt; print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)
+
>>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)
 
1 2 3 4
 
1 2 3 4
&gt;&gt;&gt; # now swap the two points
+
>>> # now swap the two points
&gt;&gt;&gt; rc.a, rc.b = rc.b, rc.a
+
>>> rc.a, rc.b = rc.b, rc.a
&gt;&gt;&gt; print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)
+
>>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)
 
3 4 3 4
 
3 4 3 4
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Hm. We certainly expected the last statement to print <code>3 4 1 2</code>. What
+
嗯。 我们当然希望最后一条语句打印 <code>3 4 1 2</code>。 发生了什么? 以下是上面 <code>rc.a, rc.b = rc.b, rc.a</code> 行的步骤:
happened? Here are the steps of the <code>rc.a, rc.b = rc.b, rc.a</code> line above:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,652行: 第1,444行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; temp0, temp1 = rc.b, rc.a
+
<syntaxhighlight lang="python3">>>> temp0, temp1 = rc.b, rc.a
&gt;&gt;&gt; rc.a = temp0
+
>>> rc.a = temp0
&gt;&gt;&gt; rc.b = temp1
+
>>> rc.b = temp1
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Note that <code>temp0</code> and <code>temp1</code> are objects still using the internal buffer of
+
请注意,<code>temp0</code> <code>temp1</code> 是仍在使用上述 <code>rc</code> 对象的内部缓冲区的对象。 因此,执行 <code>rc.a = temp0</code> 会将 <code>temp0</code> 的缓冲区内容复制到 <code>rc</code> 的缓冲区中。 这反过来又会改变 <code>temp1</code> 的内容。 所以,最后一个赋值 <code>rc.b = temp1</code> 没有达到预期的效果。
the <code>rc</code> object above. So executing <code>rc.a = temp0</code> copies the buffer
 
contents of <code>temp0</code> into <code>rc</code> 's buffer. This, in turn, changes the
 
contents of <code>temp1</code>. So, the last assignment <code>rc.b = temp1</code>, doesn't have
 
the expected effect.
 
  
Keep in mind that retrieving sub-objects from Structure, Unions, and Arrays
+
请记住,从结构、联合和数组中检索子对象不会 ''复制'' 子对象,而是检索访问根对象的底层缓冲区的包装器对象。
doesn't ''copy'' the sub-object, instead it retrieves a wrapper object accessing
 
the root-object's underlying buffer.
 
  
Another example that may behave differently from what one would expect is this:
+
另一个可能与人们期望的行为不同的示例是:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,676行: 第1,462行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; s = c_char_p()
+
<syntaxhighlight lang="python3">>>> s = c_char_p()
&gt;&gt;&gt; s.value = b&quot;abc def ghi&quot;
+
>>> s.value = b"abc def ghi"
&gt;&gt;&gt; s.value
+
>>> s.value
 
b'abc def ghi'
 
b'abc def ghi'
&gt;&gt;&gt; s.value is s.value
+
>>> s.value is s.value
 
False
 
False
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
第1,689行: 第1,475行:
 
<div class="admonition note">
 
<div class="admonition note">
  
注解
+
笔记
  
Objects instantiated from [[#ctypes.c_char_p|<code>c_char_p</code>]] can only have their value set to bytes
+
[[#ctypes.c_char_p|c_char_p]] 实例化的对象只能将其值设置为字节或整数。
or integers.
 
  
  
 
</div>
 
</div>
Why is it printing <code>False</code>? ctypes instances are objects containing a memory
+
为什么打印 <code>False</code>ctypes 实例是包含内存块和一些 [[../../glossary#term-descriptor|描述符]] 访问内存内容的对象。 在内存块中存储 Python 对象并不存储对象本身,而是存储对象的 <code>contents</code>。 再次访问内容每次都会构造一个新的 Python 对象!
block plus some [[../../glossary#term-descriptor|<span class="xref std std-term">descriptor</span>]]s accessing the contents of the memory.
 
Storing a Python object in the memory block does not store the object itself,
 
instead the <code>contents</code> of the object is stored. Accessing the contents again
 
constructs a new Python object each time!
 
  
  
第1,707行: 第1,488行:
  
 
<span id="ctypes-variable-sized-data-types"></span>
 
<span id="ctypes-variable-sized-data-types"></span>
=== Variable-sized data types ===
+
=== 可变大小的数据类型 ===
  
[[#module-ctypes|<code>ctypes</code>]] provides some support for variable-sized arrays and structures.
+
[[#module-ctypes|ctypes]] 为可变大小的数组和结构提供了一些支持。
  
The [[#ctypes.resize|<code>resize()</code>]] function can be used to resize the memory buffer of an
+
[[#ctypes.resize|resize()]] 函数可用于调整现有 ctypes 对象的内存缓冲区大小。 该函数将对象作为第一个参数,将请求的字节大小作为第二个参数。 内存块不能小于对象类型指定的自然内存块,如果尝试这样做,则会引发 [[../exceptions#ValueError|ValueError]]
existing ctypes object. The function takes the object as first argument, and
 
the requested size in bytes as the second argument. The memory block cannot be
 
made smaller than the natural memory block specified by the objects type, a
 
[[../exceptions#ValueError|<code>ValueError</code>]] is raised if this is tried:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,721行: 第1,498行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; short_array = (c_short * 4)()
+
<syntaxhighlight lang="python3">>>> short_array = (c_short * 4)()
&gt;&gt;&gt; print(sizeof(short_array))
+
>>> print(sizeof(short_array))
 
8
 
8
&gt;&gt;&gt; resize(short_array, 4)
+
>>> resize(short_array, 4)
 
Traceback (most recent call last):
 
Traceback (most recent call last):
 
     ...
 
     ...
 
ValueError: minimum size is 8
 
ValueError: minimum size is 8
&gt;&gt;&gt; resize(short_array, 32)
+
>>> resize(short_array, 32)
&gt;&gt;&gt; sizeof(short_array)
+
>>> sizeof(short_array)
 
32
 
32
&gt;&gt;&gt; sizeof(type(short_array))
+
>>> sizeof(type(short_array))
 
8
 
8
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
This is nice and fine, but how would one access the additional elements
+
这很好也很好,但是如何访问包含在这个数组中的附加元素呢? 由于该类型仍然只知道 4 个元素,因此访问其他元素时会出错:
contained in this array? Since the type still only knows about 4 elements, we
 
get errors accessing other elements:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,746行: 第1,521行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; short_array[:]
+
<syntaxhighlight lang="python3">>>> short_array[:]
 
[0, 0, 0, 0]
 
[0, 0, 0, 0]
&gt;&gt;&gt; short_array[7]
+
>>> short_array[7]
 
Traceback (most recent call last):
 
Traceback (most recent call last):
 
     ...
 
     ...
 
IndexError: invalid index
 
IndexError: invalid index
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Another way to use variable-sized data types with [[#module-ctypes|<code>ctypes</code>]] is to use the
+
将可变大小数据类型与 [[#module-ctypes|ctypes]] 一起使用的另一种方法是使用 Python 的动态特性,并在已知所需大小后(重新)定义数据类型,具体情况具体分析。
dynamic nature of Python, and (re-)define the data type after the required size
 
is already known, on a case by case basis.
 
  
  
第1,768行: 第1,541行:
  
 
<span id="ctypes-ctypes-reference"></span>
 
<span id="ctypes-ctypes-reference"></span>
== ctypes reference ==
+
== ctypes 参考 ==
  
 
<div id="finding-shared-libraries" class="section">
 
<div id="finding-shared-libraries" class="section">
  
 
<span id="ctypes-finding-shared-libraries"></span>
 
<span id="ctypes-finding-shared-libraries"></span>
=== Finding shared libraries ===
+
=== 查找共享库 ===
  
When programming in a compiled language, shared libraries are accessed when
+
使用编译语言编程时,在编译/链接程序以及运行程序时访问共享库。
compiling/linking a program, and when the program is run.
 
  
The purpose of the <code>find_library()</code> function is to locate a library in a way
+
<code>find_library()</code> 函数的目的是以类似于编译器或运行时加载器所做的方式(在具有多个共享库版本的平台上应加载最新版本)的方式定位库,而 ctypes 库加载器就像程序运行时一样,直接调用运行时加载器。
similar to what the compiler or runtime loader does (on platforms with several
 
versions of a shared library the most recent should be loaded), while the ctypes
 
library loaders act like when a program is run, and call the runtime loader
 
directly.
 
  
The <code>ctypes.util</code> module provides a function which can help to determine
+
<code>ctypes.util</code> 模块提供了一个函数,可以帮助确定要加载的库。
the library to load.
 
  
; <code>ctypes.util.</code><code>find_library</code><span class="sig-paren">(</span>''<span class="n">name</span>''<span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.util.</span></span><span class="sig-name descname"><span class="pre">find_library</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>''<span class="sig-paren">)</span>
: Try to find a library and return a pathname. ''name'' is the library name without any prefix like ''lib'', suffix like <code>.so</code>, <code>.dylib</code> or version number (this is the form used for the posix linker option <code>-l</code>). If no library can be found, returns <code>None</code>.
+
: 尝试查找库并返回路径名。 ''name'' 是没有任何前缀的库名,如 ''lib'',后缀如 <code>.so</code>, <code>.dylib</code> 或版本号(这是用于 posix 的形式链接器选项 <code>-l</code>)。 如果找不到库,则返回 <code>None</code>
  
The exact functionality is system dependent.
+
确切的功能取决于系统。
  
On Linux, <code>find_library()</code> tries to run external programs
+
Linux 上,<code>find_library()</code> 尝试运行外部程序(<code>/sbin/ldconfig</code><code>gcc</code><code>objdump</code> <code>ld</code>)来查找库文件。 它返回库文件的文件名。
(<code>/sbin/ldconfig</code>, <code>gcc</code>, <code>objdump</code> and <code>ld</code>) to find the library file.
 
It returns the filename of the library file.
 
  
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<span class="versionmodified changed">3.6 版更改: </span>On Linux, the value of the environment variable <code>LD_LIBRARY_PATH</code> is used
+
<span class="versionmodified changed"> 3.6 版本变更: </span> Linux 上,如果通过任何其他方式无法找到库,则在搜索库时使用环境变量 <code>LD_LIBRARY_PATH</code> 的值。
when searching for libraries, if a library cannot be found by any other means.
 
  
  
 
</div>
 
</div>
Here are some examples:
+
这里有些例子:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,809行: 第1,573行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes.util import find_library
+
<syntaxhighlight lang="python3">>>> from ctypes.util import find_library
&gt;&gt;&gt; find_library(&quot;m&quot;)
+
>>> find_library("m")
 
'libm.so.6'
 
'libm.so.6'
&gt;&gt;&gt; find_library(&quot;c&quot;)
+
>>> find_library("c")
 
'libc.so.6'
 
'libc.so.6'
&gt;&gt;&gt; find_library(&quot;bz2&quot;)
+
>>> find_library("bz2")
 
'libbz2.so.1.0'
 
'libbz2.so.1.0'
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
On OS X, <code>find_library()</code> tries several predefined naming schemes and paths
+
在 macOS 上,<code>find_library()</code> 尝试多个预定义的命名方案和路径来定位库,如果成功则返回完整路径名:
to locate the library, and returns a full pathname if successful:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,828行: 第1,591行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes.util import find_library
+
<syntaxhighlight lang="python3">>>> from ctypes.util import find_library
&gt;&gt;&gt; find_library(&quot;c&quot;)
+
>>> find_library("c")
 
'/usr/lib/libc.dylib'
 
'/usr/lib/libc.dylib'
&gt;&gt;&gt; find_library(&quot;m&quot;)
+
>>> find_library("m")
 
'/usr/lib/libm.dylib'
 
'/usr/lib/libm.dylib'
&gt;&gt;&gt; find_library(&quot;bz2&quot;)
+
>>> find_library("bz2")
 
'/usr/lib/libbz2.dylib'
 
'/usr/lib/libbz2.dylib'
&gt;&gt;&gt; find_library(&quot;AGL&quot;)
+
>>> find_library("AGL")
 
'/System/Library/Frameworks/AGL.framework/AGL'
 
'/System/Library/Frameworks/AGL.framework/AGL'
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
On Windows, <code>find_library()</code> searches along the system search path, and
+
Windows 上,<code>find_library()</code> 沿着系统搜索路径搜索,并返回完整路径名,但由于没有预定义的命名方案,像 <code>find_library(&quot;c&quot;)</code> 这样的调用将失败并返回 <code>None</code>
returns the full pathname, but since there is no predefined naming scheme a call
 
like <code>find_library(&quot;c&quot;)</code> will fail and return <code>None</code>.
 
  
If wrapping a shared library with [[#module-ctypes|<code>ctypes</code>]], it ''may'' be better to determine
+
如果使用 [[#module-ctypes|ctypes]] 包装共享库,''可能'' 更好地在开发时确定共享库名称,并将其硬编码到包装器模块中而不是使用 <code>find_library()</code>在运行时定位库。
the shared library name at development time, and hardcode that into the wrapper
 
module instead of using <code>find_library()</code> to locate the library at runtime.
 
  
  
第1,855行: 第1,614行:
  
 
<span id="ctypes-loading-shared-libraries"></span>
 
<span id="ctypes-loading-shared-libraries"></span>
=== Loading shared libraries ===
+
=== 加载共享库 ===
  
There are several ways to load shared libraries into the Python process. One
+
有几种方法可以将共享库加载到 Python 进程中。 一种方法是实例化以下类之一:
way is to instantiate one of the following classes:
 
  
 
<dl>
 
<dl>
<dt>''class'' <code>ctypes.</code><code>CDLL</code><span class="sig-paren">(</span>''<span class="n">name</span>'', ''<span class="n">mode</span><span class="o">=</span><span class="default_value">DEFAULT_MODE</span>'', ''<span class="n">handle</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">use_errno</span><span class="o">=</span><span class="default_value">False</span>'', ''<span class="n">use_last_error</span><span class="o">=</span><span class="default_value">False</span>'', ''<span class="n">winmode</span><span class="o">=</span><span class="default_value">0</span>''<span class="sig-paren">)</span></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">CDLL</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">mode</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">DEFAULT_MODE</span></span>'', ''<span class="n"><span class="pre">handle</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">use_errno</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span>'', ''<span class="n"><span class="pre">use_last_error</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span>'', ''<span class="n"><span class="pre">winmode</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Instances of this class represent loaded shared libraries. Functions in these
+
<dd><p>此类的实例表示加载的共享库。 这些库中的函数使用标准 C 调用约定,并假定返回 <span class="xref c c-texpr">int</span></p>
libraries use the standard C calling convention, and are assumed to return
+
<p>Windows 上,即使 DLL 名称存在,创建 [[#ctypes.CDLL|CDLL]] 实例也可能会失败。 当未找到加载的 DLL 的依赖 DLL 时,会引发 [[../exceptions#OSError|OSError]] 错误,并显示消息 ''[WinError 126] 找不到指定的模块”。'' 此错误消息不会不包含丢失的 DLL 的名称,因为 Windows API 不返回此信息,使此错误难以诊断。 要解决此错误并确定未找到哪个 DLL,您需要查找相关 DLL 列表并使用 Windows 调试和跟踪工具确定未找到哪个 DLL。</p></dd></dl>
<span class="xref c c-texpr">int</span>.</p>
 
<p>On Windows creating a [[#ctypes.CDLL|<code>CDLL</code>]] instance may fail even if the DLL name
 
exists. When a dependent DLL of the loaded DLL is not found, a
 
[[../exceptions#OSError|<code>OSError</code>]] error is raised with the message ''&quot;[WinError 126] The
 
specified module could not be found&quot;.'' This error message does not contain
 
the name of the missing DLL because the Windows API does not return this
 
information making this error hard to diagnose. To resolve this error and
 
determine which DLL is not found, you need to find the list of dependent
 
DLLs and determine which one is not found using Windows debugging and
 
tracing tools.</p></dd></dl>
 
  
 
<div class="admonition seealso">
 
<div class="admonition seealso">
  
参见
+
也可以看看
  
[https://docs.microsoft.com/cpp/build/reference/dependents Microsoft DUMPBIN tool]
+
[https://docs.microsoft.com/cpp/build/reference/dependents Microsoft DUMPBIN 工具] - 查找 DLL 依赖项的工具。
-- A tool to find DLL dependents.
 
  
  
 
</div>
 
</div>
 
<dl>
 
<dl>
<dt>''class'' <code>ctypes.</code><code>OleDLL</code><span class="sig-paren">(</span>''<span class="n">name</span>'', ''<span class="n">mode</span><span class="o">=</span><span class="default_value">DEFAULT_MODE</span>'', ''<span class="n">handle</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">use_errno</span><span class="o">=</span><span class="default_value">False</span>'', ''<span class="n">use_last_error</span><span class="o">=</span><span class="default_value">False</span>'', ''<span class="n">winmode</span><span class="o">=</span><span class="default_value">0</span>''<span class="sig-paren">)</span></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">OleDLL</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">mode</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">DEFAULT_MODE</span></span>'', ''<span class="n"><span class="pre">handle</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">use_errno</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span>'', ''<span class="n"><span class="pre">use_last_error</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span>'', ''<span class="n"><span class="pre">winmode</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Windows only: Instances of this class represent loaded shared libraries,
+
<dd><p>仅限 Windows:此类的实例表示加载的共享库,这些库中的函数使用 <code>stdcall</code> 调用约定,并假定返回特定于 Windows 的 [[#ctypes.HRESULT|HRESULT]] 代码。 [[#ctypes.HRESULT|HRESULT]] 值包含指定函数调用是失败还是成功的信息,以及其他错误代码。 如果返回值表示失败,则会自动引发 [[../exceptions#OSError|OSError]]</p>
functions in these libraries use the <code>stdcall</code> calling convention, and are
 
assumed to return the windows specific [[#ctypes.HRESULT|<code>HRESULT</code>]] code. [[#ctypes.HRESULT|<code>HRESULT</code>]]
 
values contain information specifying whether the function call failed or
 
succeeded, together with additional error code. If the return value signals a
 
failure, an [[../exceptions#OSError|<code>OSError</code>]] is automatically raised.</p>
 
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.3 版更改: </span>[[../exceptions#WindowsError|<code>WindowsError</code>]] used to be raised.</p>
+
<p><span class="versionmodified changed"> 3.3 版更改: </span>[[../exceptions#WindowsError|WindowsError]] 曾经被提出。</p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
 
<dl>
 
<dl>
<dt>''class'' <code>ctypes.</code><code>WinDLL</code><span class="sig-paren">(</span>''<span class="n">name</span>'', ''<span class="n">mode</span><span class="o">=</span><span class="default_value">DEFAULT_MODE</span>'', ''<span class="n">handle</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">use_errno</span><span class="o">=</span><span class="default_value">False</span>'', ''<span class="n">use_last_error</span><span class="o">=</span><span class="default_value">False</span>'', ''<span class="n">winmode</span><span class="o">=</span><span class="default_value">0</span>''<span class="sig-paren">)</span></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">WinDLL</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">mode</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">DEFAULT_MODE</span></span>'', ''<span class="n"><span class="pre">handle</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">use_errno</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span>'', ''<span class="n"><span class="pre">use_last_error</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span>'', ''<span class="n"><span class="pre">winmode</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Windows only: Instances of this class represent loaded shared libraries,
+
<dd><p>仅限 Windows:此类的实例表示加载的共享库,这些库中的函数使用 <code>stdcall</code> 调用约定,并假定默认返回 <span class="xref c c-texpr">int</span></p>
functions in these libraries use the <code>stdcall</code> calling convention, and are
+
<p>Windows CE 上仅使用标准调用约定,为方便起见,[[#ctypes.WinDLL|WinDLL]] [[#ctypes.OleDLL|OleDLL]] 使用此平台上的标准调用约定。</p></dd></dl>
assumed to return <span class="xref c c-texpr">int</span> by default.</p>
 
<p>On Windows CE only the standard calling convention is used, for convenience the
 
[[#ctypes.WinDLL|<code>WinDLL</code>]] and [[#ctypes.OleDLL|<code>OleDLL</code>]] use the standard calling convention on this
 
platform.</p></dd></dl>
 
  
The Python [[../../glossary#term-global-interpreter-lock|<span class="xref std std-term">global interpreter lock</span>]] is released before calling any
+
Python [[../../glossary#term-global-interpreter-lock|全局解释器锁]]在调用这些库导出的任何函数之前释放,之后重新获取。
function exported by these libraries, and reacquired afterwards.
 
  
 
<dl>
 
<dl>
<dt>''class'' <code>ctypes.</code><code>PyDLL</code><span class="sig-paren">(</span>''<span class="n">name</span>'', ''<span class="n">mode</span><span class="o">=</span><span class="default_value">DEFAULT_MODE</span>'', ''<span class="n">handle</span><span class="o">=</span><span class="default_value">None</span>''<span class="sig-paren">)</span></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">PyDLL</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>'', ''<span class="n"><span class="pre">mode</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">DEFAULT_MODE</span></span>'', ''<span class="n"><span class="pre">handle</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Instances of this class behave like [[#ctypes.CDLL|<code>CDLL</code>]] instances, except that the
+
<dd><p>此类的实例的行为类似于 [[#ctypes.CDLL|CDLL]] 实例,除了 Python GIL 在函数调用期间是 ''不是'' 释放的,并且在函数执行后检查 Python 错误标志。 如果设置了错误标志,则会引发 Python 异常。</p>
Python GIL is ''not'' released during the function call, and after the function
+
<p>因此,这仅对直接调用 Python C api 函数有用。</p></dd></dl>
execution the Python error flag is checked. If the error flag is set, a Python
 
exception is raised.</p>
 
<p>Thus, this is only useful to call Python C api functions directly.</p></dd></dl>
 
  
All these classes can be instantiated by calling them with at least one
+
所有这些类都可以通过使用至少一个参数(共享库的路径名)调用它们来实例化。 如果你有一个已经加载的共享库的现有句柄,它可以作为 <code>handle</code> 命名参数传递,否则底层平台 <code>dlopen</code> <code>LoadLibrary</code> 函数用于加载库进入进程,并得到它的句柄。
argument, the pathname of the shared library. If you have an existing handle to
 
an already loaded shared library, it can be passed as the <code>handle</code> named
 
parameter, otherwise the underlying platforms <code>dlopen</code> or <code>LoadLibrary</code>
 
function is used to load the library into the process, and to get a handle to
 
it.
 
  
The ''mode'' parameter can be used to specify how the library is loaded. For
+
''mode'' 参数可用于指定库的加载方式。 有关详细信息,请参阅 ''dlopen(3)'' 联机帮助页。 在 Windows 上,''mode'' 被忽略。 在 posix 系统上,始终添加 RTLD_NOW,并且不可配置。
details, consult the ''[https://manpages.debian.org/dlopen(3) dlopen(3)]'' manpage. On Windows, ''mode'' is
 
ignored. On posix systems, RTLD_NOW is always added, and is not
 
configurable.
 
  
The ''use_errno'' parameter, when set to true, enables a ctypes mechanism that
+
''use_errno'' 参数设置为 true 时,启用 ctypes 机制,允许以安全的方式访问系统 [[../errno#module-errno|errno]] 错误号。 [[#module-ctypes|ctypes]] 维护系统 [[../errno#module-errno|errno]] 变量的线程本地副本; 如果您调用使用 <code>use_errno=True</code> 创建的外部函数,那么在函数调用与 ctypes 私有副本交换之前的 [[../errno#module-errno|errno]] 值,函数调用后会立即发生同样的情况。
allows accessing the system [[../errno#module-errno|<code>errno</code>]] error number in a safe way.
 
[[#module-ctypes|<code>ctypes</code>]] maintains a thread-local copy of the systems [[../errno#module-errno|<code>errno</code>]]
 
variable; if you call foreign functions created with <code>use_errno=True</code> then the
 
[[../errno#module-errno|<code>errno</code>]] value before the function call is swapped with the ctypes private
 
copy, the same happens immediately after the function call.
 
  
The function [[#ctypes.get_errno|<code>ctypes.get_errno()</code>]] returns the value of the ctypes private
+
函数 [[#ctypes.get_errno|ctypes.get_errno()]] 返回 ctypes 私有副本的值,函数 [[#ctypes.set_errno|ctypes.set_errno()]] ctypes 私有副本更改为新值并返回之前的值.
copy, and the function [[#ctypes.set_errno|<code>ctypes.set_errno()</code>]] changes the ctypes private copy
 
to a new value and returns the former value.
 
  
The ''use_last_error'' parameter, when set to true, enables the same mechanism for
+
''use_last_error'' 参数设置为 true 时,为由 [[#ctypes.GetLastError|GetLastError()]] <code>SetLastError()</code> Windows API 函数管理的 Windows 错误代码启用相同的机制; [[#ctypes.get_last_error|ctypes.get_last_error()]] [[#ctypes.set_last_error|ctypes.set_last_error()]] 用于请求和更改 windows 错误代码的 ctypes 私有副本。
the Windows error code which is managed by the [[#ctypes.GetLastError|<code>GetLastError()</code>]] and
 
<code>SetLastError()</code> Windows API functions; [[#ctypes.get_last_error|<code>ctypes.get_last_error()</code>]] and
 
[[#ctypes.set_last_error|<code>ctypes.set_last_error()</code>]] are used to request and change the ctypes private
 
copy of the windows error code.
 
  
The ''winmode'' parameter is used on Windows to specify how the library is loaded
+
''winmode'' 参数在 Windows 上用于指定库的加载方式(因为 ''mode'' 被忽略)。 它采用对 Win32 API <code>LoadLibraryEx</code> 标志参数有效的任何值。 省略时,默认使用导致最安全的 DLL 加载的标志来避免诸如 DLL 劫持之类的问题。 将完整路径传递给 DLL 是确保加载正确的库和依赖项的最安全方法。
(since ''mode'' is ignored). It takes any value that is valid for the Win32 API
 
<code>LoadLibraryEx</code> flags parameter. When omitted, the default is to use the flags
 
that result in the most secure DLL load to avoiding issues such as DLL
 
hijacking. Passing the full path to the DLL is the safest way to ensure the
 
correct library and dependencies are loaded.
 
  
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<span class="versionmodified changed">3.8 版更改: </span>Added ''winmode'' parameter.
+
<span class="versionmodified changed"> 3.8 版更改: </span> 添加 ''winmode'' 参数。
  
  
 
</div>
 
</div>
; <code>ctypes.</code><code>RTLD_GLOBAL</code>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">RTLD_GLOBAL</span></span>
: Flag to use as ''mode'' parameter. On platforms where this flag is not available, it is defined as the integer zero.
+
: 用作 ''mode'' 参数的标志。 在此标志不可用的平台上,它被定义为整数零。
  
; <code>ctypes.</code><code>RTLD_LOCAL</code>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">RTLD_LOCAL</span></span>
: Flag to use as ''mode'' parameter. On platforms where this is not available, it is the same as ''RTLD_GLOBAL''.
+
: 用作 ''mode'' 参数的标志。 在不可用的平台上,它与 ''RTLD_GLOBAL'' 相同。
  
; <code>ctypes.</code><code>DEFAULT_MODE</code>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">DEFAULT_MODE</span></span>
: The default mode which is used to load shared libraries. On OSX 10.3, this is ''RTLD_GLOBAL'', otherwise it is the same as ''RTLD_LOCAL''.
+
: 用于加载共享库的默认模式。 在 OSX 10.3 上,这是 ''RTLD_GLOBAL'',否则与 ''RTLD_LOCAL'' 相同。
  
Instances of these classes have no public methods. Functions exported by the
+
这些类的实例没有公共方法。 共享库导出的函数可以作为属性或索引进行访问。 请注意,通过属性访问函数会缓存结果,因此每次重复访问它都会返回相同的对象。 另一方面,通过索引访问它每次都会返回一个新对象:
shared library can be accessed as attributes or by index. Please note that
 
accessing the function through an attribute caches the result and therefore
 
accessing it repeatedly returns the same object each time. On the other hand,
 
accessing it through an index returns a new object each time:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第1,979行: 第1,685行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes import CDLL
+
<syntaxhighlight lang="python3">>>> from ctypes import CDLL
&gt;&gt;&gt; libc = CDLL(&quot;libc.so.6&quot;)  # On Linux
+
>>> libc = CDLL("libc.so.6")  # On Linux
&gt;&gt;&gt; libc.time == libc.time
+
>>> libc.time == libc.time
 
True
 
True
&gt;&gt;&gt; libc['time'] == libc['time']
+
>>> libc['time'] == libc['time']
False</pre>
+
False</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The following public attributes are available, their name starts with an
+
以下公共属性可用,它们的名称以下划线开头,以免与导出的函数名称冲突:
underscore to not clash with exported function names:
 
  
; <code>PyDLL.</code><code>_handle</code>
+
; <span class="sig-prename descclassname"><span class="pre">PyDLL.</span></span><span class="sig-name descname"><span class="pre">_handle</span></span>
: The system handle used to access the library.
+
: 用于访问库的系统句柄。
  
; <code>PyDLL.</code><code>_name</code>
+
; <span class="sig-prename descclassname"><span class="pre">PyDLL.</span></span><span class="sig-name descname"><span class="pre">_name</span></span>
: The name of the library passed in the constructor.
+
: 在构造函数中传递的库的名称。
  
Shared libraries can also be loaded by using one of the prefabricated objects,
+
共享库也可以通过使用预制对象之一加载,这些对象是 [[#ctypes.LibraryLoader|LibraryLoader]] 类的实例,通过调用 <code>LoadLibrary()</code> 方法,或通过检索库作为加载器的属性实例。
which are instances of the [[#ctypes.LibraryLoader|<code>LibraryLoader</code>]] class, either by calling the
 
<code>LoadLibrary()</code> method, or by retrieving the library as attribute of the
 
loader instance.
 
  
 
<dl>
 
<dl>
<dt>''class'' <code>ctypes.</code><code>LibraryLoader</code><span class="sig-paren">(</span>''<span class="n">dlltype</span>''<span class="sig-paren">)</span></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">LibraryLoader</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">dlltype</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Class which loads shared libraries. ''dlltype'' should be one of the
+
<dd><p>加载共享库的类。 ''dlltype'' 应该是 [[#ctypes.CDLL|CDLL]][[#ctypes.PyDLL|PyDLL]][[#ctypes.WinDLL|WinDLL]] [[#ctypes.OleDLL|OleDLL]] 类型之一。</p>
[[#ctypes.CDLL|<code>CDLL</code>]], [[#ctypes.PyDLL|<code>PyDLL</code>]], [[#ctypes.WinDLL|<code>WinDLL</code>]], or [[#ctypes.OleDLL|<code>OleDLL</code>]] types.</p>
+
<p><code>__getattr__()</code> 具有特殊的行为:它允许通过访问共享库作为库加载器实例的属性来加载它。 结果被缓存,因此重复的属性访问每次都返回相同的库。</p>
<p><code>__getattr__()</code> has special behavior: It allows loading a shared library by
 
accessing it as attribute of a library loader instance. The result is cached,
 
so repeated attribute accesses return the same library each time.</p>
 
 
<dl>
 
<dl>
<dt><code>LoadLibrary</code><span class="sig-paren">(</span>''<span class="n">name</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">LoadLibrary</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Load a shared library into the process and return it. This method always
+
<dd><p>将共享库加载到进程中并返回。 此方法始终返回库的新实例。</p></dd></dl>
returns a new instance of the library.</p></dd></dl>
 
 
</dd></dl>
 
</dd></dl>
  
These prefabricated library loaders are available:
+
这些预制库加载器可用:
  
; <code>ctypes.</code><code>cdll</code>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">cdll</span></span>
: Creates [[#ctypes.CDLL|<code>CDLL</code>]] instances.
+
: 创建 [[#ctypes.CDLL|CDLL]] 实例。
  
; <code>ctypes.</code><code>windll</code>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">windll</span></span>
: Windows only: Creates [[#ctypes.WinDLL|<code>WinDLL</code>]] instances.
+
: 仅限 Windows:创建 [[#ctypes.WinDLL|WinDLL]] 实例。
  
; <code>ctypes.</code><code>oledll</code>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">oledll</span></span>
: Windows only: Creates [[#ctypes.OleDLL|<code>OleDLL</code>]] instances.
+
: 仅限 Windows:创建 [[#ctypes.OleDLL|OleDLL]] 实例。
  
; <code>ctypes.</code><code>pydll</code>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">pydll</span></span>
: Creates [[#ctypes.PyDLL|<code>PyDLL</code>]] instances.
+
: 创建 [[#ctypes.PyDLL|PyDLL]] 实例。
  
For accessing the C Python api directly, a ready-to-use Python shared library
+
为了直接访问 C Python api,可以使用现成的 Python 共享库对象:
object is available:
 
  
; <code>ctypes.</code><code>pythonapi</code>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">pythonapi</span></span>
: An instance of [[#ctypes.PyDLL|<code>PyDLL</code>]] that exposes Python C API functions as attributes. Note that all these functions are assumed to return C <span class="xref c c-texpr">int</span>, which is of course not always the truth, so you have to assign the correct <code>restype</code> attribute to use these functions.
+
: [[#ctypes.PyDLL|PyDLL]] 的一个实例,将 Python C API 函数公开为属性。 请注意,所有这些函数都假定返回 C <span class="xref c c-texpr">int</span>,这当然并不总是正确的,因此您必须分配正确的 <code>restype</code> 属性才能使用这些函数。
 
 
Loading a library through any of these objects raises an
 
[[../sys#auditing|<span class="std std-ref">auditing event</span>]] <code>ctypes.dlopen</code> with string argument
 
<code>name</code>, the name used to load the library.
 
 
 
Accessing a function on a loaded library raises an auditing event
 
<code>ctypes.dlsym</code> with arguments <code>library</code> (the library object) and <code>name</code>
 
(the symbol's name as a string or integer).
 
 
 
In cases when only the library handle is available rather than the object,
 
accessing a function raises an auditing event <code>ctypes.dlsym/handle</code> with
 
arguments <code>handle</code> (the raw library handle) and <code>name</code>.
 
  
  
第2,053行: 第1,738行:
  
 
<span id="ctypes-foreign-functions"></span>
 
<span id="ctypes-foreign-functions"></span>
=== Foreign functions ===
+
=== 外部函数 ===
  
As explained in the previous section, foreign functions can be accessed as
+
如上一节所述,外部函数可以作为加载的共享库的属性进行访问。 以这种方式创建的函数对象默认接受任意数量的参数,接受任何 ctypes 数据实例作为参数,并返回库加载器指定的默认结果类型。 它们是私有类的实例:
attributes of loaded shared libraries. The function objects created in this way
 
by default accept any number of arguments, accept any ctypes data instances as
 
arguments, and return the default result type specified by the library loader.
 
They are instances of a private class:
 
  
 
<dl>
 
<dl>
<dt>''class'' <code>ctypes.</code><code>_FuncPtr</code></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">_FuncPtr</span></span></dt>
<dd><p>Base class for C callable foreign functions.</p>
+
<dd><p>C 可调用外部函数的基类。</p>
<p>Instances of foreign functions are also C compatible data types; they
+
<p>外部函数的实例也是 C 兼容的数据类型; 它们代表 C 函数指针。</p>
represent C function pointers.</p>
+
<p>这种行为可以通过分配给外部函数对象的特殊属性来定制。</p>
<p>This behavior can be customized by assigning to special attributes of the
 
foreign function object.</p>
 
 
<dl>
 
<dl>
<dt><code>restype</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">restype</span></span></dt>
<dd><p>Assign a ctypes type to specify the result type of the foreign function.
+
<dd><p>分配一个 ctypes 类型来指定外部函数的结果类型。 将 <code>None</code> 用于 <span class="xref c c-texpr">void</span>,该函数不返回任何内容。</p>
Use <code>None</code> for <span class="xref c c-texpr">void</span>, a function not returning anything.</p>
+
<p>可以分配一个不是 ctypes 类型的可调用 Python 对象,在这种情况下,假定函数返回 C <span class="xref c c-texpr">int</span>,并且将使用此整数调用可调用对象,允许进一步处理或错误检查。 不推荐使用它,为了更灵活的后处理或错误检查,请使用 ctypes 数据类型作为 [[#ctypes._FuncPtr.restype|restype]] 并将可调用对象分配给 [[#ctypes._FuncPtr.errcheck|errcheck]] 属性。</p></dd></dl>
<p>It is possible to assign a callable Python object that is not a ctypes
 
type, in this case the function is assumed to return a C <span class="xref c c-texpr">int</span>, and
 
the callable will be called with this integer, allowing further
 
processing or error checking. Using this is deprecated, for more flexible
 
post processing or error checking use a ctypes data type as
 
[[#ctypes._FuncPtr.restype|<code>restype</code>]] and assign a callable to the [[#ctypes._FuncPtr.errcheck|<code>errcheck</code>]] attribute.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>argtypes</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">argtypes</span></span></dt>
<dd><p>Assign a tuple of ctypes types to specify the argument types that the
+
<dd><p>分配一个 ctypes 类型的元组来指定函数接受的参数类型。 使用 <code>stdcall</code> 调用约定的函数只能使用与此元组长度相同数量的参数来调用; 使用 C 调用约定的函数也接受额外的、未指定的参数。</p>
function accepts. Functions using the <code>stdcall</code> calling convention can
+
<p>当调用外部函数时,每个实参都传递给 [[#ctypes._FuncPtr.argtypes|argtypes]] 元组中项的 <code>from_param()</code> 类方法,该方法允许将实参适配到外部函数接受。 例如, [[#ctypes._FuncPtr.argtypes|argtypes]] 元组中的 [[#ctypes.c_char_p|c_char_p]] 项将使用 ctypes 转换规则将作为参数传递的字符串转换为字节对象。</p>
only be called with the same number of arguments as the length of this
+
<p>新:现在可以将项目放入不是 ctypes 类型的 argtypes 中,但每个项目必须有一个 <code>from_param()</code> 方法,该方法返回一个可用作参数的值(整数、字符串、ctypes 实例)。 这允许定义可以适应自定义对象作为函数参数的适配器。</p></dd></dl>
tuple; functions using the C calling convention accept additional,
 
unspecified arguments as well.</p>
 
<p>When a foreign function is called, each actual argument is passed to the
 
<code>from_param()</code> class method of the items in the [[#ctypes._FuncPtr.argtypes|<code>argtypes</code>]]
 
tuple, this method allows adapting the actual argument to an object that
 
the foreign function accepts. For example, a [[#ctypes.c_char_p|<code>c_char_p</code>]] item in
 
the [[#ctypes._FuncPtr.argtypes|<code>argtypes</code>]] tuple will convert a string passed as argument into
 
a bytes object using ctypes conversion rules.</p>
 
<p>New: It is now possible to put items in argtypes which are not ctypes
 
types, but each item must have a <code>from_param()</code> method which returns a
 
value usable as argument (integer, string, ctypes instance). This allows
 
defining adapters that can adapt custom objects as function parameters.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>errcheck</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">errcheck</span></span></dt>
<dd><p>Assign a Python function or another callable to this attribute. The
+
<dd><p>为该属性分配一个 Python 函数或另一个可调用函数。 将使用三个或更多参数调用可调用对象:</p>
callable will be called with three or more arguments:</p>
 
 
<dl>
 
<dl>
<dt><code>callable</code><span class="sig-paren">(</span>''<span class="n">result</span>'', ''<span class="n">func</span>'', ''<span class="n">arguments</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">callable</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">result</span></span>'', ''<span class="n"><span class="pre">func</span></span>'', ''<span class="n"><span class="pre">arguments</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>''result'' is what the foreign function returns, as specified by the
+
<dd><p>''result'' 是外部函数返回的内容,由 <code>restype</code> 属性指定。</p>
<code>restype</code> attribute.</p>
+
<p>''func'' 是外部函数对象本身,这允许重用相同的可调用对象来检查或后处理多个函数的结果。</p>
<p>''func'' is the foreign function object itself, this allows reusing the
+
<p>''arguments'' 是一个包含最初传递给函数调用的参数的元组,这允许对所用参数的行为进行专门化。</p></dd></dl>
same callable object to check or post process the results of several
 
functions.</p>
 
<p>''arguments'' is a tuple containing the parameters originally passed to
 
the function call, this allows specializing the behavior on the
 
arguments used.</p></dd></dl>
 
  
<p>The object that this function returns will be returned from the
+
<p>此函数返回的对象将从外部函数调用返回,但如果外部函数调用失败,它也可以检查结果值并引发异常。</p></dd></dl>
foreign function call, but it can also check the result value
 
and raise an exception if the foreign function call failed.</p></dd></dl>
 
 
</dd></dl>
 
</dd></dl>
  
; ''exception'' <code>ctypes.</code><code>ArgumentError</code>
+
; ''<span class="pre">exception</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">ArgumentError</span></span>
: This exception is raised when a foreign function call cannot convert one of the passed arguments.
+
: 当外部函数调用无法转换传递的参数之一时,会引发此异常。
 
 
On Windows, when a foreign function call raises a system exception (for
 
example, due to an access violation), it will be captured and replaced with
 
a suitable Python exception. Further, an auditing event
 
<code>ctypes.seh_exception</code> with argument <code>code</code> will be raised, allowing an
 
audit hook to replace the exception with its own.
 
 
 
Some ways to invoke foreign function calls may raise an auditing event
 
<code>ctypes.call_function</code> with arguments <code>function pointer</code> and <code>arguments</code>.
 
  
  
第2,134行: 第1,778行:
  
 
<span id="ctypes-function-prototypes"></span>
 
<span id="ctypes-function-prototypes"></span>
=== Function prototypes ===
+
=== 函数原型 ===
  
Foreign functions can also be created by instantiating function prototypes.
+
也可以通过实例化函数原型来创建外部函数。 函数原型类似于 C 中的函数原型; 它们描述了一个函数(返回类型、参数类型、调用约定)而不定义实现。 工厂函数必须使用所需的结果类型和函数的参数类型来调用,并且可以用作装饰器工厂,因此可以通过 <code>@wrapper</code> 语法应用于函数。 有关示例,请参阅 [[#ctypes-callback-functions|回调函数]]
Function prototypes are similar to function prototypes in C; they describe a
 
function (return type, argument types, calling convention) without defining an
 
implementation. The factory functions must be called with the desired result
 
type and the argument types of the function, and can be used as decorator
 
factories, and as such, be applied to functions through the <code>@wrapper</code> syntax.
 
See [[#ctypes-callback-functions|<span class="std std-ref">Callback functions</span>]] for examples.
 
  
; <code>ctypes.</code><code>CFUNCTYPE</code><span class="sig-paren">(</span>''<span class="n">restype</span>'', ''<span class="o">*</span><span class="n">argtypes</span>'', ''<span class="n">use_errno</span><span class="o">=</span><span class="default_value">False</span>'', ''<span class="n">use_last_error</span><span class="o">=</span><span class="default_value">False</span>''<span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">CFUNCTYPE</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">restype</span></span>'', ''<span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">argtypes</span></span>'', ''<span class="n"><span class="pre">use_errno</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span>'', ''<span class="n"><span class="pre">use_last_error</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span>''<span class="sig-paren">)</span>
: The returned function prototype creates functions that use the standard C calling convention. The function will release the GIL during the call. If ''use_errno'' is set to true, the ctypes private copy of the system [[../errno#module-errno|<code>errno</code>]] variable is exchanged with the real [[../errno#module-errno|<code>errno</code>]] value before and after the call; ''use_last_error'' does the same for the Windows error code.
+
: 返回的函数原型创建使用标准 C 调用约定的函数。 该函数将在调用期间释放 GIL。 如果''use_errno''设置为true,系统[[../errno#module-errno|errno]]变量的ctypes私有副本在调用前后与真实的[[../errno#module-errno|errno]]值交换; ''use_last_error'' Windows 错误代码执行相同操作。
  
; <code>ctypes.</code><code>WINFUNCTYPE</code><span class="sig-paren">(</span>''<span class="n">restype</span>'', ''<span class="o">*</span><span class="n">argtypes</span>'', ''<span class="n">use_errno</span><span class="o">=</span><span class="default_value">False</span>'', ''<span class="n">use_last_error</span><span class="o">=</span><span class="default_value">False</span>''<span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">WINFUNCTYPE</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">restype</span></span>'', ''<span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">argtypes</span></span>'', ''<span class="n"><span class="pre">use_errno</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span>'', ''<span class="n"><span class="pre">use_last_error</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">False</span></span>''<span class="sig-paren">)</span>
: Windows only: The returned function prototype creates functions that use the <code>stdcall</code> calling convention, except on Windows CE where [[#ctypes.WINFUNCTYPE|<code>WINFUNCTYPE()</code>]] is the same as [[#ctypes.CFUNCTYPE|<code>CFUNCTYPE()</code>]]. The function will release the GIL during the call. ''use_errno'' and ''use_last_error'' have the same meaning as above.
+
: 仅限 Windows:返回的函数原型创建使用 <code>stdcall</code> 调用约定的函数,但在 Windows CE 上除外,其中 [[#ctypes.WINFUNCTYPE|WINFUNCTYPE()]] [[#ctypes.CFUNCTYPE|CFUNCTYPE()]] 相同。 该函数将在调用期间释放 GIL。 ''use_errno'' ''use_last_error'' 含义同上。
  
; <code>ctypes.</code><code>PYFUNCTYPE</code><span class="sig-paren">(</span>''<span class="n">restype</span>'', ''<span class="o">*</span><span class="n">argtypes</span>''<span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">PYFUNCTYPE</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">restype</span></span>'', ''<span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">argtypes</span></span>''<span class="sig-paren">)</span>
: The returned function prototype creates functions that use the Python calling convention. The function will ''not'' release the GIL during the call.
+
: 返回的函数原型创建使用 Python 调用约定的函数。 该函数将 '''' 在调用过程中释放 GIL。
  
Function prototypes created by these factory functions can be instantiated in
+
这些工厂函数创建的函数原型可以通过不同的方式实例化,具体取决于调用中参数的类型和数量:
different ways, depending on the type and number of the parameters in the call:
 
  
 
<blockquote><div>
 
<blockquote><div>
  
; <code>prototype</code><span class="sig-paren">(</span>''<span class="n">address</span>''<span class="sig-paren">)</span>
+
; <span class="sig-name descname"><span class="pre">prototype</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">address</span></span>''<span class="sig-paren">)</span>
: Returns a foreign function at the specified address which must be an integer.
+
: 返回指定地址处的外部函数,该函数必须是整数。
  
; <code>prototype</code><span class="sig-paren">(</span>''<span class="n">callable</span>''<span class="sig-paren">)</span>
+
; <span class="sig-name descname"><span class="pre">prototype</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">callable</span></span>''<span class="sig-paren">)</span>
: Create a C callable function (a callback function) from a Python ''callable''.
+
: Python ''callable'' 创建 C 可调用函数(回调函数)。
  
; <code>prototype</code><span class="sig-paren">(</span>''func_spec''<span class="optional">[</span>, ''paramflags''<span class="optional">]</span><span class="sig-paren">)</span>
+
; <span class="sig-name descname"><span class="pre">prototype</span></span><span class="sig-paren">(</span>''<span class="pre">func_spec</span>''<span class="optional">[</span>, ''<span class="pre">paramflags</span>''<span class="optional">]</span><span class="sig-paren">)</span>
: Returns a foreign function exported by a shared library. ''func_spec'' must be a 2-tuple <code>(name_or_ordinal, library)</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.
+
: 返回共享库导出的外部函数。 ''func_spec'' 必须是一个二元组 <code>(name_or_ordinal, library)</code>。 第一项是作为字符串的导出函数的名称,或者作为小整数的导出函数的序数。 第二项是共享库实例。
  
 
<dl>
 
<dl>
<dt><code>prototype</code><span class="sig-paren">(</span>''vtbl_index'', ''name''<span class="optional">[</span>, ''paramflags''<span class="optional">[</span>, ''iid''<span class="optional">]</span><span class="optional">]</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">prototype</span></span><span class="sig-paren">(</span>''<span class="pre">vtbl_index</span>'', ''<span class="pre">name</span>''<span class="optional">[</span>, ''<span class="pre">paramflags</span>''<span class="optional">[</span>, ''<span class="pre">iid</span>''<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. ''vtbl_index'' is
+
<dd><p>返回将调用 COM 方法的外部函数。 ''vtbl_index''是虚函数表的索引,一个小的非负整数。 ''name'' COM 方法的名称。 ''iid'' 是一个可选的指向接口标识符的指针,用于扩展错误报告。</p>
the index into the virtual function table, a small non-negative
+
<p>COM 方法使用特殊的调用约定:除了 <code>argtypes</code> 元组中指定的那些参数之外,它们还需要一个指向 COM 接口的指针作为第一个参数。</p></dd></dl>
integer. ''name'' is name of the COM method. ''iid'' 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>argtypes</code> tuple.</p></dd></dl>
 
  
The optional ''paramflags'' parameter creates foreign function wrappers with much
+
可选的 ''paramflags'' 参数创建具有比上述功能更多功能的外部函数包装器。
more functionality than the features described above.
 
  
''paramflags'' must be a tuple of the same length as <code>argtypes</code>.
+
''paramflags'' 必须是与 <code>argtypes</code> 长度相同的元组。
  
Each item in this tuple contains further information about a parameter, it must
+
此元组中的每一项都包含有关参数的更多信息,它必须是包含一项、两项或三项的元组。
be a tuple containing one, two, or three items.
 
  
The first item is an integer containing a combination of direction
+
第一项是一个整数,包含参数的方向标志组合:
flags for the parameter:
 
  
 
<blockquote><div>
 
<blockquote><div>
  
 
; 1
 
; 1
: Specifies an input parameter to the function.
+
: 指定函数的输入参数。
 
; 2
 
; 2
: Output parameter. The foreign function fills in a value.
+
: 输出参数。 外部函数填充一个值。
 
; 4
 
; 4
: Input parameter which defaults to the integer zero.
+
: 默认为整数零的输入参数。
  
  
 
</div></blockquote>
 
</div></blockquote>
The optional second item is the parameter name as string. If this is specified,
+
可选的第二项是字符串形式的参数名称。 如果指定了此项,则可以使用命名参数调用外部函数。
the foreign function can be called with named parameters.
 
  
The optional third item is the default value for this parameter.
+
可选的第三项是该参数的默认值。
  
  
 
</div></blockquote>
 
</div></blockquote>
This example demonstrates how to wrap the Windows <code>MessageBoxW</code> function so
+
此示例演示如何包装 Windows <code>MessageBoxW</code> 函数,以便它支持默认参数和命名参数。 windows 头文件中的 C 声明是这样的:
that it supports default parameters and named arguments. The C declaration from
 
the windows header file is this:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第2,214行: 第1,840行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>WINUSERAPI int WINAPI
+
<syntaxhighlight lang="python3">WINUSERAPI int WINAPI
 
MessageBoxW(
 
MessageBoxW(
 
     HWND hWnd,
 
     HWND hWnd,
 
     LPCWSTR lpText,
 
     LPCWSTR lpText,
 
     LPCWSTR lpCaption,
 
     LPCWSTR lpCaption,
     UINT uType);</pre>
+
     UINT uType);</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Here is the wrapping with [[#module-ctypes|<code>ctypes</code>]]:
+
这是 [[#module-ctypes|ctypes]] 的包装:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第2,230行: 第1,856行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes import c_int, WINFUNCTYPE, windll
+
<syntaxhighlight lang="python3">>>> from ctypes import c_int, WINFUNCTYPE, windll
&gt;&gt;&gt; from ctypes.wintypes import HWND, LPCWSTR, UINT
+
>>> from ctypes.wintypes import HWND, LPCWSTR, UINT
&gt;&gt;&gt; prototype = WINFUNCTYPE(c_int, HWND, LPCWSTR, LPCWSTR, UINT)
+
>>> prototype = WINFUNCTYPE(c_int, HWND, LPCWSTR, LPCWSTR, UINT)
&gt;&gt;&gt; paramflags = (1, &quot;hwnd&quot;, 0), (1, &quot;text&quot;, &quot;Hi&quot;), (1, &quot;caption&quot;, &quot;Hello from ctypes&quot;), (1, &quot;flags&quot;, 0)
+
>>> paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1, "caption", "Hello from ctypes"), (1, "flags", 0)
&gt;&gt;&gt; MessageBox = prototype((&quot;MessageBoxW&quot;, windll.user32), paramflags)</pre>
+
>>> MessageBox = prototype(("MessageBoxW", windll.user32), paramflags)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
The <code>MessageBox</code> foreign function can now be called in these ways:
+
<code>MessageBox</code> 外部函数现在可以通过以下方式调用:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第2,245行: 第1,871行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; MessageBox()
+
<syntaxhighlight lang="python3">>>> MessageBox()
&gt;&gt;&gt; MessageBox(text=&quot;Spam, spam, spam&quot;)
+
>>> MessageBox(text="Spam, spam, spam")
&gt;&gt;&gt; MessageBox(flags=2, text=&quot;foo bar&quot;)</pre>
+
>>> MessageBox(flags=2, text="foo bar")</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
A second example demonstrates output parameters. The win32 <code>GetWindowRect</code>
+
第二个示例演示输出参数。 win32 <code>GetWindowRect</code> 函数通过将它们复制到调用者必须提供的 <code>RECT</code> 结构中来检索指定窗口的尺寸。 这是 C 声明:
function retrieves the dimensions of a specified window by copying them into
 
<code>RECT</code> structure that the caller has to supply. Here is the C declaration:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第2,260行: 第1,884行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>WINUSERAPI BOOL WINAPI
+
<syntaxhighlight lang="python3">WINUSERAPI BOOL WINAPI
 
GetWindowRect(
 
GetWindowRect(
 
     HWND hWnd,
 
     HWND hWnd,
     LPRECT lpRect);</pre>
+
     LPRECT lpRect);</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Here is the wrapping with [[#module-ctypes|<code>ctypes</code>]]:
+
这是 [[#module-ctypes|ctypes]] 的包装:
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第2,274行: 第1,898行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; from ctypes import POINTER, WINFUNCTYPE, windll, WinError
+
<syntaxhighlight lang="python3">>>> from ctypes import POINTER, WINFUNCTYPE, windll, WinError
&gt;&gt;&gt; from ctypes.wintypes import BOOL, HWND, RECT
+
>>> from ctypes.wintypes import BOOL, HWND, RECT
&gt;&gt;&gt; prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT))
+
>>> prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT))
&gt;&gt;&gt; paramflags = (1, &quot;hwnd&quot;), (2, &quot;lprect&quot;)
+
>>> paramflags = (1, "hwnd"), (2, "lprect")
&gt;&gt;&gt; GetWindowRect = prototype((&quot;GetWindowRect&quot;, windll.user32), paramflags)
+
>>> GetWindowRect = prototype(("GetWindowRect", windll.user32), paramflags)
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
Functions with output parameters will automatically return the output parameter
+
如果有一个输出参数值,带有输出参数的函数将自动返回输出参数值,或者当有多个输出参数值时返回一个包含输出参数值的元组,因此 GetWindowRect 函数现在在调用时返回一个 RECT 实例。
value if there is a single one, or a tuple containing the output parameter
 
values when there are more than one, so the GetWindowRect function now returns a
 
RECT instance, when called.
 
  
Output parameters can be combined with the <code>errcheck</code> protocol to do
+
输出参数可以结合<code>errcheck</code>协议进行进一步的输出处理和错误检查。 win32 <code>GetWindowRect</code> api 函数返回一个 <code>BOOL</code> 来表示成功或失败,因此该函数可以进行错误检查,并在 api 调用失败时引发异常:
further output processing and error checking. The win32 <code>GetWindowRect</code> api
 
function returns a <code>BOOL</code> to signal success or failure, so this function could
 
do the error checking, and raises an exception when the api call failed:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第2,298行: 第1,916行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; def errcheck(result, func, args):
+
<syntaxhighlight lang="python3">>>> def errcheck(result, func, args):
 
...    if not result:
 
...    if not result:
 
...        raise WinError()
 
...        raise WinError()
 
...    return args
 
...    return args
 
...
 
...
&gt;&gt;&gt; GetWindowRect.errcheck = errcheck
+
>>> GetWindowRect.errcheck = errcheck
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
If the <code>errcheck</code> function returns the argument tuple it receives
+
如果 <code>errcheck</code> 函数返回它接收到的参数元组不变,[[#module-ctypes|ctypes]] 继续它对输出参数所做的正常处理。 如果你想返回一个窗口坐标元组而不是一个 <code>RECT</code> 实例,你可以检索函数中的字段并返回它们,正常处理将不再发生:
unchanged, [[#module-ctypes|<code>ctypes</code>]] continues the normal processing it does on the output
 
parameters. If you want to return a tuple of window coordinates instead of a
 
<code>RECT</code> instance, you can retrieve the fields in the function and return them
 
instead, the normal processing will no longer take place:
 
  
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
第2,319行: 第1,933行:
 
<div class="highlight">
 
<div class="highlight">
  
<pre>&gt;&gt;&gt; def errcheck(result, func, args):
+
<syntaxhighlight lang="python3">>>> def errcheck(result, func, args):
 
...    if not result:
 
...    if not result:
 
...        raise WinError()
 
...        raise WinError()
第2,325行: 第1,939行:
 
...    return rc.left, rc.top, rc.bottom, rc.right
 
...    return rc.left, rc.top, rc.bottom, rc.right
 
...
 
...
&gt;&gt;&gt; GetWindowRect.errcheck = errcheck
+
>>> GetWindowRect.errcheck = errcheck
&gt;&gt;&gt;</pre>
+
>>></syntaxhighlight>
  
 
</div>
 
</div>
第2,336行: 第1,950行:
  
 
<span id="ctypes-utility-functions"></span>
 
<span id="ctypes-utility-functions"></span>
=== Utility functions ===
+
=== 实用功能 ===
  
<dl>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">addressof</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">obj</span></span>''<span class="sig-paren">)</span>
<dt><code>ctypes.</code><code>addressof</code><span class="sig-paren">(</span>''<span class="n">obj</span>''<span class="sig-paren">)</span></dt>
+
: 以整数形式返回内存缓冲区的地址。 ''obj'' 必须是 ctypes 类型的实例。
<dd><p>Returns the address of the memory buffer as integer. ''obj'' must be an
 
instance of a ctypes type.</p>
 
<p>Raises an [[../sys#auditing|<span class="std std-ref">auditing event</span>]] <code>ctypes.addressof</code> with argument <code>obj</code>.</p></dd></dl>
 
  
; <code>ctypes.</code><code>alignment</code><span class="sig-paren">(</span>''<span class="n">obj_or_type</span>''<span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">alignment</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">obj_or_type</span></span>''<span class="sig-paren">)</span>
: Returns the alignment requirements of a ctypes type. ''obj_or_type'' must be a ctypes type or instance.
+
: 返回 ctypes 类型的对齐要求。 ''obj_or_type'' 必须是 ctypes 类型或实例。
  
 
<dl>
 
<dl>
<dt><code>ctypes.</code><code>byref</code><span class="sig-paren">(</span>''obj''<span class="optional">[</span>, ''offset''<span class="optional">]</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">byref</span></span><span class="sig-paren">(</span>''<span class="pre">obj</span>''<span class="optional">[</span>, ''<span class="pre">offset</span>''<span class="optional">]</span><span class="sig-paren">)</span></dt>
<dd><p>Returns a light-weight pointer to ''obj'', which must be an instance of a
+
<dd><p>返回一个指向 ''obj'' 的轻量级指针,它必须是一个 ctypes 类型的实例。 ''offset'' 默认为零,并且必须是将添加到内部指针值的整数。</p>
ctypes type. ''offset'' defaults to zero, and must be an integer that will be
+
<p><code>byref(obj, offset)</code> 对应这个 C 代码:</p>
added to the internal pointer value.</p>
 
<p><code>byref(obj, offset)</code> corresponds to this C code:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>(((char *)&amp;obj) + offset)</pre>
+
<syntaxhighlight lang="python3">(((char *)&obj) + offset)</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>The returned object can only be used as a foreign function call parameter.
+
<p>返回的对象只能用作外部函数调用参数。 它的行为类似于 <code>pointer(obj)</code>,但构建速度要快得多。</p></dd></dl>
It behaves similar to <code>pointer(obj)</code>, but the construction is a lot faster.</p></dd></dl>
 
  
; <code>ctypes.</code><code>cast</code><span class="sig-paren">(</span>''<span class="n">obj</span>'', ''<span class="n">type</span>''<span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">cast</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">obj</span></span>'', ''<span class="n"><span class="pre">type</span></span>''<span class="sig-paren">)</span>
: This function is similar to the cast operator in C. It returns a new instance of ''type'' which points to the same memory block as ''obj''. ''type'' must be a pointer type, and ''obj'' must be an object that can be interpreted as a pointer.
+
: 此函数类似于 C 中的强制转换运算符。 它返回一个 ''type'' 的新实例,它指向与 ''obj'' 相同的内存块。 ''type'' 必须是指针类型,''obj'' 必须是可以解释为指针的对象。
  
 
<dl>
 
<dl>
<dt><code>ctypes.</code><code>create_string_buffer</code><span class="sig-paren">(</span>''<span class="n">init_or_size</span>'', ''<span class="n">size</span><span class="o">=</span><span class="default_value">None</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">create_string_buffer</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">init_or_size</span></span>'', ''<span class="n"><span class="pre">size</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This function creates a mutable character buffer. The returned object is a
+
<dd><p>此函数创建一个可变字符缓冲区。 返回的对象是 [[#ctypes.c_char|c_char]] 的 ctypes 数组。</p>
ctypes array of [[#ctypes.c_char|<code>c_char</code>]].</p>
+
<p>''init_or_size'' 必须是指定数组大小的整数,或用于初始化数组项的字节对象。</p>
<p>''init_or_size'' must be an integer which specifies the size of the array, or a
+
<p>如果将字节对象指定为第一个参数,则缓冲区将比其长度大一个项目,以便数组中的最后一个元素是 NUL 终止字符。 一个整数可以作为第二个参数传递,如果不应该使用字节的长度,它允许指定数组的大小。</p></dd></dl>
bytes object which will be used to initialize the array items.</p>
 
<p>If a bytes object is specified as first argument, the buffer is made one item
 
larger than its length so that the last element in the array is a NUL
 
termination character. An integer can be passed as second argument which allows
 
specifying the size of the array if the length of the bytes should not be used.</p>
 
<p>Raises an [[../sys#auditing|<span class="std std-ref">auditing event</span>]] <code>ctypes.create_string_buffer</code> with arguments <code>init</code>, <code>size</code>.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>ctypes.</code><code>create_unicode_buffer</code><span class="sig-paren">(</span>''<span class="n">init_or_size</span>'', ''<span class="n">size</span><span class="o">=</span><span class="default_value">None</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">create_unicode_buffer</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">init_or_size</span></span>'', ''<span class="n"><span class="pre">size</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This function creates a mutable unicode character buffer. The returned object is
+
<dd><p>此函数创建一个可变的 unicode 字符缓冲区。 返回的对象是 [[#ctypes.c_wchar|c_wchar]] 的 ctypes 数组。</p>
a ctypes array of [[#ctypes.c_wchar|<code>c_wchar</code>]].</p>
+
<p>''init_or_size'' 必须是指定数组大小的整数,或用于初始化数组项的字符串。</p>
<p>''init_or_size'' must be an integer which specifies the size of the array, or a
+
<p>如果将字符串指定为第一个参数,则缓冲区将比字符串的长度大一个项目,以便数组中的最后一个元素是 NUL 终止字符。 一个整数可以作为第二个参数传递,如果不应该使用字符串的长度,它允许指定数组的大小。</p></dd></dl>
string which will be used to initialize the array items.</p>
 
<p>If a string is specified as first argument, the buffer is made one item
 
larger than the length of the string so that the last element in the array is a
 
NUL termination character. An integer can be passed as second argument which
 
allows specifying the size of the array if the length of the string should not
 
be used.</p>
 
<p>Raises an [[../sys#auditing|<span class="std std-ref">auditing event</span>]] <code>ctypes.create_unicode_buffer</code> with arguments <code>init</code>, <code>size</code>.</p></dd></dl>
 
  
; <code>ctypes.</code><code>DllCanUnloadNow</code><span class="sig-paren">(</span><span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">DllCanUnloadNow</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span>
: Windows only: This function is a hook which allows implementing in-process COM servers with ctypes. It is called from the DllCanUnloadNow function that the _ctypes extension dll exports.
+
: 仅适用于 Windows:此函数是一个钩子,它允许使用 ctypes 实现进程内 COM 服务器。 它是从 _ctypes 扩展 dll 导出的 DllCanUnloadNow 函数调用的。
  
; <code>ctypes.</code><code>DllGetClassObject</code><span class="sig-paren">(</span><span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">DllGetClassObject</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span>
: Windows only: This function is a hook which allows implementing in-process COM servers with ctypes. It is called from the DllGetClassObject function that the <code>_ctypes</code> extension dll exports.
+
: 仅适用于 Windows:此函数是一个钩子,它允许使用 ctypes 实现进程内 COM 服务器。 它是从 <code>_ctypes</code> 扩展 dll 导出的 DllGetClassObject 函数调用的。
  
 
<dl>
 
<dl>
<dt><code>ctypes.util.</code><code>find_library</code><span class="sig-paren">(</span>''<span class="n">name</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">ctypes.util.</span></span><span class="sig-name descname"><span class="pre">find_library</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">name</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Try to find a library and return a pathname. ''name'' is the library name
+
<dd><p>尝试查找库并返回路径名。 ''name'' 是没有任何前缀的库名,如 <code>lib</code>,后缀如 <code>.so</code>, <code>.dylib</code> 或版本号(这是用于 posix 链接器的形式选项 <code>-l</code>)。 如果找不到库,则返回 <code>None</code></p>
without any prefix like <code>lib</code>, suffix like <code>.so</code>, <code>.dylib</code> or version
+
<p>确切的功能取决于系统。</p></dd></dl>
number (this is the form used for the posix linker option <code>-l</code>). If
 
no library can be found, returns <code>None</code>.</p>
 
<p>The exact functionality is system dependent.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>ctypes.util.</code><code>find_msvcrt</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">ctypes.util.</span></span><span class="sig-name descname"><span class="pre">find_msvcrt</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
<dd><p>Windows only: return the filename of the VC runtime library used by Python,
+
<dd><p>仅限 Windows:返回 Python 和扩展模块使用的 VC 运行时库的文件名。 如果无法确定库的名称,则返回 <code>None</code></p>
and by the extension modules. If the name of the library cannot be
+
<p>如果您需要释放内存,例如,由调用 <code>free(void *)</code> 的扩展模块分配,那么使用分配内存的同一库中的函数很重要。</p></dd></dl>
determined, <code>None</code> is returned.</p>
 
<p>If you need to free memory, for example, allocated by an extension module
 
with a call to the <code>free(void *)</code>, it is important that you use the
 
function in the same library that allocated the memory.</p></dd></dl>
 
  
; <code>ctypes.</code><code>FormatError</code><span class="sig-paren">(</span><span class="optional">[</span>''code''<span class="optional">]</span><span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">FormatError</span></span><span class="sig-paren">(</span><span class="optional">[</span>''<span class="pre">code</span>''<span class="optional">]</span><span class="sig-paren">)</span>
: Windows only: Returns a textual description of the error code ''code''. If no error code is specified, the last error code is used by calling the Windows api function GetLastError.
+
: 仅限 Windows:返回错误代码 ''code'' 的文本描述。 如果未指定错误代码,则通过调用 Windows api 函数 GetLastError 使用最后一个错误代码。
  
; <code>ctypes.</code><code>GetLastError</code><span class="sig-paren">(</span><span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">GetLastError</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span>
: Windows only: Returns the last error code set by Windows in the calling thread. This function calls the Windows GetLastError() function directly, it does not return the ctypes-private copy of the error code.
+
: 仅限 Windows:返回 Windows 在调用线程中设置的最后一个错误代码。 此函数直接调用Windows GetLastError() 函数,它不返回错误代码的ctypes-private 副本。
  
<dl>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">get_errno</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span>
<dt><code>ctypes.</code><code>get_errno</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
: 返回调用线程中系统 [[../errno#module-errno|errno]] 变量的 ctypes-private 副本的当前值。
<dd><p>Returns the current value of the ctypes-private copy of the system
 
[[../errno#module-errno|<code>errno</code>]] variable in the calling thread.</p>
 
<p>Raises an [[../sys#auditing|<span class="std std-ref">auditing event</span>]] <code>ctypes.get_errno</code> with no arguments.</p></dd></dl>
 
  
<dl>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">get_last_error</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span>
<dt><code>ctypes.</code><code>get_last_error</code><span class="sig-paren">(</span><span class="sig-paren">)</span></dt>
+
: 仅限 Windows:返回调用线程中系统 <code>LastError</code> 变量的 ctypes-private 副本的当前值。
<dd><p>Windows only: returns the current value of the ctypes-private copy of the system
 
<code>LastError</code> variable in the calling thread.</p>
 
<p>Raises an [[../sys#auditing|<span class="std std-ref">auditing event</span>]] <code>ctypes.get_last_error</code> with no arguments.</p></dd></dl>
 
  
; <code>ctypes.</code><code>memmove</code><span class="sig-paren">(</span>''<span class="n">dst</span>'', ''<span class="n">src</span>'', ''<span class="n">count</span>''<span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">memmove</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">dst</span></span>'', ''<span class="n"><span class="pre">src</span></span>'', ''<span class="n"><span class="pre">count</span></span>''<span class="sig-paren">)</span>
: Same as the standard C memmove library function: copies ''count'' bytes from ''src'' to ''dst''. ''dst'' and ''src'' must be integers or ctypes instances that can be converted to pointers.
+
: 与标准 C memmove 库函数相同:将 ''count'' 个字节从 ''src'' 复制到 ''dst''''dst'' ''src'' 必须是可以转换为指针的整数或 ctypes 实例。
  
; <code>ctypes.</code><code>memset</code><span class="sig-paren">(</span>''<span class="n">dst</span>'', ''<span class="n">c</span>'', ''<span class="n">count</span>''<span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">memset</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">dst</span></span>'', ''<span class="n"><span class="pre">c</span></span>'', ''<span class="n"><span class="pre">count</span></span>''<span class="sig-paren">)</span>
: Same as the standard C memset library function: fills the memory block at address ''dst'' with ''count'' bytes of value ''c''. ''dst'' must be an integer specifying an address, or a ctypes instance.
+
: 与标准 C memset 库函数相同:用 ''count'' 个字节的值 ''c'' 填充地址 ''dst'' 处的内存块。 ''dst'' 必须是指定地址或 ctypes 实例的整数。
  
; <code>ctypes.</code><code>POINTER</code><span class="sig-paren">(</span>''<span class="n">type</span>''<span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">POINTER</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">type</span></span>''<span class="sig-paren">)</span>
: This factory function creates and returns a new ctypes pointer type. Pointer types are cached and reused internally, so calling this function repeatedly is cheap. ''type'' must be a ctypes type.
+
: 这个工厂函数创建并返回一个新的 ctypes 指针类型。 指针类型在内部被缓存和重用,所以重复调用这个函数很便宜。 ''type'' 必须是 ctypes 类型。
  
 
<dl>
 
<dl>
<dt><code>ctypes.</code><code>pointer</code><span class="sig-paren">(</span>''<span class="n">obj</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">pointer</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">obj</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This function creates a new pointer instance, pointing to ''obj''. The returned
+
<dd><p>此函数创建一个新的指针实例,指向 ''obj''。 返回的对象的类型为 <code>POINTER(type(obj))</code></p>
object is of the type <code>POINTER(type(obj))</code>.</p>
+
<p>注意:如果您只想将指向对象的指针传递给外部函数调用,您应该使用 <code>byref(obj)</code>,它要快得多。</p></dd></dl>
<p>Note: If you just want to pass a pointer to an object to a foreign function
 
call, you should use <code>byref(obj)</code> which is much faster.</p></dd></dl>
 
  
; <code>ctypes.</code><code>resize</code><span class="sig-paren">(</span>''<span class="n">obj</span>'', ''<span class="n">size</span>''<span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">resize</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">obj</span></span>'', ''<span class="n"><span class="pre">size</span></span>''<span class="sig-paren">)</span>
: This function resizes the internal memory buffer of ''obj'', which must be an instance of a ctypes type. It is not possible to make the buffer smaller than the native size of the objects type, as given by <code>sizeof(type(obj))</code>, but it is possible to enlarge the buffer.
+
: 此函数调整 ''obj'' 的内部内存缓冲区大小,它必须是 ctypes 类型的实例。 不可能使缓冲区小于对象类型的原始大小,如 <code>sizeof(type(obj))</code> 给出的,但可以扩大缓冲区。
  
<dl>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">set_errno</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">value</span></span>''<span class="sig-paren">)</span>
<dt><code>ctypes.</code><code>set_errno</code><span class="sig-paren">(</span>''<span class="n">value</span>''<span class="sig-paren">)</span></dt>
+
: 将调用线程中系统 [[../errno#module-errno|errno]] 变量的 ctypes-private 副本的当前值设置为 ''value'' 并返回之前的值。
<dd><p>Set the current value of the ctypes-private copy of the system [[../errno#module-errno|<code>errno</code>]]
 
variable in the calling thread to ''value'' and return the previous value.</p>
 
<p>Raises an [[../sys#auditing|<span class="std std-ref">auditing event</span>]] <code>ctypes.set_errno</code> with argument <code>errno</code>.</p></dd></dl>
 
  
<dl>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">set_last_error</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">value</span></span>''<span class="sig-paren">)</span>
<dt><code>ctypes.</code><code>set_last_error</code><span class="sig-paren">(</span>''<span class="n">value</span>''<span class="sig-paren">)</span></dt>
+
: 仅限 Windows:将调用线程中系统 <code>LastError</code> 变量的 ctypes-private 副本的当前值设置为 ''value'' 并返回先前的值。
<dd><p>Windows only: set the current value of the ctypes-private copy of the system
 
<code>LastError</code> variable in the calling thread to ''value'' and return the
 
previous value.</p>
 
<p>Raises an [[../sys#auditing|<span class="std std-ref">auditing event</span>]] <code>ctypes.set_last_error</code> with argument <code>error</code>.</p></dd></dl>
 
  
; <code>ctypes.</code><code>sizeof</code><span class="sig-paren">(</span>''<span class="n">obj_or_type</span>''<span class="sig-paren">)</span>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">sizeof</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">obj_or_type</span></span>''<span class="sig-paren">)</span>
: Returns the size in bytes of a ctypes type or instance memory buffer. Does the same as the C <code>sizeof</code> operator.
+
: 返回 ctypes 类型或实例内存缓冲区的大小(以字节为单位)。 与 C <code>sizeof</code> 运算符相同。
  
<dl>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">string_at</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">address</span></span>'', ''<span class="n"><span class="pre">size</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">-</span> <span class="pre">1</span></span>''<span class="sig-paren">)</span>
<dt><code>ctypes.</code><code>string_at</code><span class="sig-paren">(</span>''<span class="n">address</span>'', ''<span class="n">size</span><span class="o">=</span><span class="default_value">- 1</span>''<span class="sig-paren">)</span></dt>
+
: 此函数返回从内存地址 ''address'' 开始的 C 字符串作为字节对象。 如果指定了大小,则将其用作大小,否则假定字符串以零结尾。
<dd><p>This function returns the C string starting at memory address ''address'' as a bytes
 
object. If size is specified, it is used as size, otherwise the string is assumed
 
to be zero-terminated.</p>
 
<p>Raises an [[../sys#auditing|<span class="std std-ref">auditing event</span>]] <code>ctypes.string_at</code> with arguments <code>address</code>, <code>size</code>.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>ctypes.</code><code>WinError</code><span class="sig-paren">(</span>''<span class="n">code</span><span class="o">=</span><span class="default_value">None</span>'', ''<span class="n">descr</span><span class="o">=</span><span class="default_value">None</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">WinError</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">code</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>'', ''<span class="n"><span class="pre">descr</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Windows only: this function is probably the worst-named thing in ctypes. It
+
<dd><p>仅限 Windows:这个函数可能是 ctypes 中命名最差的东西。 它创建了一个 OSError 实例。 如果未指定 ''code'',则调用 <code>GetLastError</code> 以确定错误代码。 如果未指定 ''descr'',则调用 [[#ctypes.FormatError|FormatError()]] 以获取错误的文本描述。</p>
creates an instance of OSError. If ''code'' is not specified,
 
<code>GetLastError</code> is called to determine the error code. If ''descr'' is not
 
specified, [[#ctypes.FormatError|<code>FormatError()</code>]] is called to get a textual description of the
 
error.</p>
 
 
<div class="versionchanged">
 
<div class="versionchanged">
  
<p><span class="versionmodified changed">3.3 版更改: </span>An instance of [[../exceptions#WindowsError|<code>WindowsError</code>]] used to be created.</p>
+
<p><span class="versionmodified changed"> 3.3 版更改: </span> 曾经创建 [[../exceptions#WindowsError|WindowsError]] 的实例。</p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
<dl>
+
; <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">wstring_at</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">address</span></span>'', ''<span class="n"><span class="pre">size</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">-</span> <span class="pre">1</span></span>''<span class="sig-paren">)</span>
<dt><code>ctypes.</code><code>wstring_at</code><span class="sig-paren">(</span>''<span class="n">address</span>'', ''<span class="n">size</span><span class="o">=</span><span class="default_value">- 1</span>''<span class="sig-paren">)</span></dt>
+
: 此函数以字符串形式返回从内存地址 ''address'' 开始的宽字符串。 如果指定了 ''size'',则将其用作字符串的字符数,否则假定字符串以零结尾。
<dd><p>This function returns the wide character string starting at memory address
 
''address'' as a string. If ''size'' is specified, it is used as the number of
 
characters of the string, otherwise the string is assumed to be
 
zero-terminated.</p>
 
<p>Raises an [[../sys#auditing|<span class="std std-ref">auditing event</span>]] <code>ctypes.wstring_at</code> with arguments <code>address</code>, <code>size</code>.</p></dd></dl>
 
  
  
第2,502行: 第2,062行:
  
 
<span id="ctypes-data-types"></span>
 
<span id="ctypes-data-types"></span>
=== Data types ===
+
=== 数据类型 ===
  
 
<dl>
 
<dl>
<dt>''class'' <code>ctypes.</code><code>_CData</code></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">_CData</span></span></dt>
<dd><p>This non-public class is the common base class of all ctypes data types.
+
<dd><p>这个非公共类是所有 ctypes 数据类型的公共基类。 除其他外,所有 ctypes 类型实例都包含一个存储 C 兼容数据的内存块; 内存块的地址由 [[#ctypes.addressof|addressof()]] 辅助函数返回。 另一个实例变量公开为 [[#ctypes._CData._objects|_objects]]; 这包含其他需要保持活动状态的 Python 对象,以防内存块包含指针。</p>
Among other things, all ctypes type instances contain a memory block that
+
<p>ctypes数据类型的常用方法,这些都是类方法(准确的说是[[../../glossary#term-metaclass|元类]]的方法):</p>
hold C compatible data; the address of the memory block is returned by the
 
[[#ctypes.addressof|<code>addressof()</code>]] helper function. Another instance variable is exposed as
 
[[#ctypes._CData._objects|<code>_objects</code>]]; this contains other Python objects that need to be kept
 
alive in case the memory block contains pointers.</p>
 
<p>Common methods of ctypes data types, these are all class methods (to be
 
exact, they are methods of the [[../../glossary#term-metaclass|<span class="xref std std-term">metaclass</span>]]):</p>
 
 
<dl>
 
<dl>
<dt><code>from_buffer</code><span class="sig-paren">(</span>''source''<span class="optional">[</span>, ''offset''<span class="optional">]</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">from_buffer</span></span><span class="sig-paren">(</span>''<span class="pre">source</span>''<span class="optional">[</span>, ''<span class="pre">offset</span>''<span class="optional">]</span><span class="sig-paren">)</span></dt>
<dd><p>This method returns a ctypes instance that shares the buffer of the
+
<dd><p>此方法返回一个 ctypes 实例,该实例共享 ''source'' 对象的缓冲区。 ''source'' 对象必须支持可写缓冲区接口。 可选的 ''offset'' 参数以字节为单位指定源缓冲区的偏移量; 默认为零。 如果源缓冲区不够大,则会引发 [[../exceptions#ValueError|ValueError]]</p></dd></dl>
''source'' object. The ''source'' object must support the writeable buffer
 
interface. The optional ''offset'' parameter specifies an offset into the
 
source buffer in bytes; the default is zero. If the source buffer is not
 
large enough a [[../exceptions#ValueError|<code>ValueError</code>]] is raised.</p>
 
<p>Raises an [[../sys#auditing|<span class="std std-ref">auditing event</span>]] <code>ctypes.cdata/buffer</code> with arguments <code>pointer</code>, <code>size</code>, <code>offset</code>.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>from_buffer_copy</code><span class="sig-paren">(</span>''source''<span class="optional">[</span>, ''offset''<span class="optional">]</span><span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">from_buffer_copy</span></span><span class="sig-paren">(</span>''<span class="pre">source</span>''<span class="optional">[</span>, ''<span class="pre">offset</span>''<span class="optional">]</span><span class="sig-paren">)</span></dt>
<dd><p>This method creates a ctypes instance, copying the buffer from the
+
<dd><p>此方法创建一个 ctypes 实例,从必须可读的 ''source'' 对象缓冲区复制缓冲区。 可选的 ''offset'' 参数以字节为单位指定源缓冲区的偏移量; 默认为零。 如果源缓冲区不够大,则会引发 [[../exceptions#ValueError|ValueError]]</p></dd></dl>
''source'' object buffer which must be readable. The optional ''offset''
 
parameter specifies an offset into the source buffer in bytes; the default
 
is zero. If the source buffer is not large enough a [[../exceptions#ValueError|<code>ValueError</code>]] is
 
raised.</p>
 
<p>Raises an [[../sys#auditing|<span class="std std-ref">auditing event</span>]] <code>ctypes.cdata/buffer</code> with arguments <code>pointer</code>, <code>size</code>, <code>offset</code>.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>from_address</code><span class="sig-paren">(</span>''<span class="n">address</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">from_address</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">address</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This method returns a ctypes type instance using the memory specified by
+
<dd><p>此方法使用 ''address'' 指定的内存返回一个 ctypes 类型实例,该内存必须是整数。</p></dd></dl>
''address'' which must be an integer.</p>
 
<p>This method, and others that indirectly call this method, raises an
 
[[../sys#auditing|<span class="std std-ref">auditing event</span>]] <code>ctypes.cdata</code> with argument
 
<code>address</code>.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>from_param</code><span class="sig-paren">(</span>''<span class="n">obj</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">from_param</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">obj</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This method adapts ''obj'' to a ctypes type. It is called with the actual
+
<dd><p>此方法使 ''obj'' 适应 ctypes 类型。 当类型存在于外部函数的 <code>argtypes</code> 元组中时,使用外部函数调用中使用的实际对象调用它; 它必须返回一个可以用作函数调用参数的对象。</p>
object used in a foreign function call when the type is present in the
+
<p>所有 ctypes 数据类型都有此类方法的默认实现,如果它是该类型的实例,则通常返回 ''obj''。 有些类型也接受其他对象。</p></dd></dl>
foreign function's <code>argtypes</code> tuple; it must return an object that
 
can be used as a function call parameter.</p>
 
<p>All ctypes data types have a default implementation of this classmethod
 
that normally returns ''obj'' if that is an instance of the type. Some
 
types accept other objects as well.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>in_dll</code><span class="sig-paren">(</span>''<span class="n">library</span>'', ''<span class="n">name</span>''<span class="sig-paren">)</span></dt>
+
<dt><span class="sig-name descname"><span class="pre">in_dll</span></span><span class="sig-paren">(</span>''<span class="n"><span class="pre">library</span></span>'', ''<span class="n"><span class="pre">name</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>This method returns a ctypes type instance exported by a shared
+
<dd><p>此方法返回共享库导出的 ctypes 类型实例。 ''name''为导出数据的符号名,''library''为加载的共享库。</p></dd></dl>
library. ''name'' is the name of the symbol that exports the data, ''library''
 
is the loaded shared library.</p></dd></dl>
 
  
<p>Common instance variables of ctypes data types:</p>
+
<p>ctypes 数据类型的常见实例变量:</p>
 
<dl>
 
<dl>
<dt><code>_b_base_</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">_b_base_</span></span></dt>
<dd><p>Sometimes ctypes data instances do not own the memory block they contain,
+
<dd><p>有时 ctypes 数据实例不拥有它们包含的内存块,而是共享基础对象的部分内存块。 [[#ctypes._CData._b_base_|_b_base_]] 只读成员是拥有内存块的根 ctypes 对象。</p></dd></dl>
instead they share part of the memory block of a base object. The
 
[[#ctypes._CData._b_base_|<code>_b_base_</code>]] read-only member is the root ctypes object that owns the
 
memory block.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>_b_needsfree_</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">_b_needsfree_</span></span></dt>
<dd><p>This read-only variable is true when the ctypes data instance has
+
<dd><p>ctypes 数据实例本身分配了内存块时,这个只读变量为真,否则为假。</p></dd></dl>
allocated the memory block itself, false otherwise.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>_objects</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">_objects</span></span></dt>
<dd><p>This member is either <code>None</code> or a dictionary containing Python objects
+
<dd><p>该成员是 <code>None</code> 或包含需要保持活动状态的 Python 对象的字典,以便内存块内容保持有效。 此对象仅用于调试; 永远不要修改这本词典的内容。</p></dd></dl>
that need to be kept alive so that the memory block contents is kept
 
valid. This object is only exposed for debugging; never modify the
 
contents of this dictionary.</p></dd></dl>
 
 
</dd></dl>
 
</dd></dl>
  
第2,582行: 第2,108行:
  
 
<span id="id1"></span>
 
<span id="id1"></span>
=== Fundamental data types ===
+
=== 基本数据类型 ===
  
 
<dl>
 
<dl>
<dt>''class'' <code>ctypes.</code><code>_SimpleCData</code></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">_SimpleCData</span></span></dt>
<dd><p>This non-public class is the base class of all fundamental ctypes data
+
<dd><p>这个非公共类是所有基本 ctypes 数据类型的基类。 在这里提到它是因为它包含基本 ctypes 数据类型的公共属性。 [[#ctypes._SimpleCData|_SimpleCData]] [[#ctypes._CData|_CData]] 的子类,所以继承了它们的方法和属性。 现在可以腌制不包含也不包含指针的 ctypes 数据类型。</p>
types. It is mentioned here because it contains the common attributes of the
+
<p>实例有一个属性:</p>
fundamental ctypes data types. [[#ctypes._SimpleCData|<code>_SimpleCData</code>]] is a subclass of
 
[[#ctypes._CData|<code>_CData</code>]], so it inherits their methods and attributes. ctypes data
 
types that are not and do not contain pointers can now be pickled.</p>
 
<p>Instances have a single attribute:</p>
 
 
<dl>
 
<dl>
<dt><code>value</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">value</span></span></dt>
<dd><p>This attribute contains the actual value of the instance. For integer and
+
<dd><p>该属性包含实例的实际值。 对于整数和指针类型,它是一个整数,对于字符类型,它是一个单字符字节对象或字符串,对于字符指针类型,它是一个 Python 字节对象或字符串。</p>
pointer types, it is an integer, for character types, it is a single
+
<p>当从 ctypes 实例中检索 <code>value</code> 属性时,通常每次都会返回一个新对象。 [[#module-ctypes|ctypes]] ''''实现原对象返回,总是构造一个新对象。 对于所有其他 ctypes 对象实例也是如此。</p></dd></dl>
character bytes object or string, for character pointer types it is a
 
Python bytes object or string.</p>
 
<p>When the <code>value</code> attribute is retrieved from a ctypes instance, usually
 
a new object is returned each time. [[#module-ctypes|<code>ctypes</code>]] does ''not'' implement
 
original object return, always a new object is constructed. The same is
 
true for all other ctypes object instances.</p></dd></dl>
 
 
</dd></dl>
 
</dd></dl>
  
Fundamental data types, when returned as foreign function call results, or, for
+
基本数据类型在作为外部函数调用结果返回时,或者例如通过检索结构字段成员或数组项时,会透明地转换为本地 Python 类型。 换句话说,如果一个外部函数有一个 [[#ctypes.c_char_p|c_char_p]] 的 <code>restype</code>,你将总是收到一个 Python 字节对象,''而不是'' 一个 [[#ctypes.c_char_p|c_char_p]] 实例.
example, by retrieving structure field members or array items, are transparently
 
converted to native Python types. In other words, if a foreign function has a
 
<code>restype</code> of [[#ctypes.c_char_p|<code>c_char_p</code>]], you will always receive a Python bytes
 
object, ''not'' a [[#ctypes.c_char_p|<code>c_char_p</code>]] instance.
 
  
Subclasses of fundamental data types do ''not'' inherit this behavior. So, if a
+
基本数据类型的子类 ''不会'' 继承此行为。 因此,如果外部函数 <code>restype</code> [[#ctypes.c_void_p|c_void_p]] 的子类,您将从函数调用中收到该子类的实例。 当然,您可以通过访问 <code>value</code> 属性来获取指针的值。
foreign functions <code>restype</code> is a subclass of [[#ctypes.c_void_p|<code>c_void_p</code>]], you will
 
receive an instance of this subclass from the function call. Of course, you can
 
get the value of the pointer by accessing the <code>value</code> attribute.
 
  
These are the fundamental ctypes data types:
+
这些是基本的 ctypes 数据类型:
  
; ''class'' <code>ctypes.</code><code>c_byte</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_byte</span></span>
: Represents the C <span class="xref c c-texpr">signed char</span> datatype, and interprets the value as small integer. The constructor accepts an optional integer initializer; no overflow checking is done.
+
: 表示 C <span class="xref c c-texpr">signed char</span> 数据类型,并将值解释为小整数。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
  
; ''class'' <code>ctypes.</code><code>c_char</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_char</span></span>
: Represents the C <span class="xref c c-texpr">char</span> datatype, and interprets the value as a single character. The constructor accepts an optional string initializer, the length of the string must be exactly one character.
+
: 表示 C <span class="xref c c-texpr">char</span> 数据类型,并将值解释为单个字符。 构造函数接受一个可选的字符串初始化器,字符串的长度必须正好是一个字符。
  
; ''class'' <code>ctypes.</code><code>c_char_p</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_char_p</span></span>
: Represents the C <span class="xref c c-texpr">char*</span> datatype when it points to a zero-terminated string. For a general character pointer that may also point to binary data, <code>POINTER(c_char)</code> must be used. The constructor accepts an integer address, or a bytes object.
+
: 当它指向以零结尾的字符串时,表示 C <span class="xref c c-texpr">char*</span> 数据类型。 对于也可能指向二进制数据的通用字符指针,必须使用 <code>POINTER(c_char)</code>。 构造函数接受一个整数地址或一个字节对象。
  
; ''class'' <code>ctypes.</code><code>c_double</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_double</span></span>
: Represents the C <span class="xref c c-texpr">double</span> datatype. The constructor accepts an optional float initializer.
+
: 表示 C <span class="xref c c-texpr">double</span> 数据类型。 构造函数接受一个可选的浮点初始化器。
  
; ''class'' <code>ctypes.</code><code>c_longdouble</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_longdouble</span></span>
: Represents the C <span class="xref c c-texpr">long double</span> datatype. The constructor accepts an optional float initializer. On platforms where <code>sizeof(long double) == sizeof(double)</code> it is an alias to [[#ctypes.c_double|<code>c_double</code>]].
+
: 表示 C <span class="xref c c-texpr">long double</span> 数据类型。 构造函数接受一个可选的浮点初始化器。 在 <code>sizeof(long double) == sizeof(double)</code> 它是 [[#ctypes.c_double|c_double]] 的别名的平台上。
  
; ''class'' <code>ctypes.</code><code>c_float</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_float</span></span>
: Represents the C <span class="xref c c-texpr">float</span> datatype. The constructor accepts an optional float initializer.
+
: 表示 C <span class="xref c c-texpr">float</span> 数据类型。 构造函数接受一个可选的浮点初始化器。
  
; ''class'' <code>ctypes.</code><code>c_int</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_int</span></span>
: Represents the C <span class="xref c c-texpr">signed int</span> datatype. The constructor accepts an optional integer initializer; no overflow checking is done. On platforms where <code>sizeof(int) == sizeof(long)</code> it is an alias to [[#ctypes.c_long|<code>c_long</code>]].
+
: 表示 C <span class="xref c c-texpr">signed int</span> 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。 在 <code>sizeof(int) == sizeof(long)</code> 它是 [[#ctypes.c_long|c_long]] 的别名的平台上。
  
; ''class'' <code>ctypes.</code><code>c_int8</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_int8</span></span>
: Represents the C 8-bit <span class="xref c c-texpr">signed int</span> datatype. Usually an alias for [[#ctypes.c_byte|<code>c_byte</code>]].
+
: 表示 C 8 <span class="xref c c-texpr">signed int</span> 数据类型。 通常是 [[#ctypes.c_byte|c_byte]] 的别名。
  
; ''class'' <code>ctypes.</code><code>c_int16</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_int16</span></span>
: Represents the C 16-bit <span class="xref c c-texpr">signed int</span> datatype. Usually an alias for [[#ctypes.c_short|<code>c_short</code>]].
+
: 表示 C 16 <span class="xref c c-texpr">signed int</span> 数据类型。 通常是 [[#ctypes.c_short|c_short]] 的别名。
  
; ''class'' <code>ctypes.</code><code>c_int32</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_int32</span></span>
: Represents the C 32-bit <span class="xref c c-texpr">signed int</span> datatype. Usually an alias for [[#ctypes.c_int|<code>c_int</code>]].
+
: 表示 C 32 <span class="xref c c-texpr">signed int</span> 数据类型。 通常是 [[#ctypes.c_int|c_int]] 的别名。
  
; ''class'' <code>ctypes.</code><code>c_int64</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_int64</span></span>
: Represents the C 64-bit <span class="xref c c-texpr">signed int</span> datatype. Usually an alias for [[#ctypes.c_longlong|<code>c_longlong</code>]].
+
: 表示 C 64 <span class="xref c c-texpr">signed int</span> 数据类型。 通常是 [[#ctypes.c_longlong|c_longlong]] 的别名。
  
; ''class'' <code>ctypes.</code><code>c_long</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_long</span></span>
: Represents the C <span class="xref c c-texpr">signed long</span> datatype. The constructor accepts an optional integer initializer; no overflow checking is done.
+
: 表示 C <span class="xref c c-texpr">signed long</span> 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
  
; ''class'' <code>ctypes.</code><code>c_longlong</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_longlong</span></span>
: Represents the C <span class="xref c c-texpr">signed long long</span> datatype. The constructor accepts an optional integer initializer; no overflow checking is done.
+
: 表示 C <span class="xref c c-texpr">signed long long</span> 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
  
; ''class'' <code>ctypes.</code><code>c_short</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_short</span></span>
: Represents the C <span class="xref c c-texpr">signed short</span> datatype. The constructor accepts an optional integer initializer; no overflow checking is done.
+
: 表示 C <span class="xref c c-texpr">signed short</span> 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
  
; ''class'' <code>ctypes.</code><code>c_size_t</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_size_t</span></span>
: Represents the C <code>size_t</code> datatype.
+
: 表示 C <code>size_t</code> 数据类型。
  
 
<dl>
 
<dl>
<dt>''class'' <code>ctypes.</code><code>c_ssize_t</code></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_ssize_t</span></span></dt>
<dd><p>Represents the C <code>ssize_t</code> datatype.</p>
+
<dd><p>表示 C <code>ssize_t</code> 数据类型。</p>
 
<div class="versionadded">
 
<div class="versionadded">
  
<p><span class="versionmodified added">3.2 新版功能.</span></p>
+
<p><span class="versionmodified added">3.2 版中的新功能。</span></p>
  
 
</div></dd></dl>
 
</div></dd></dl>
  
; ''class'' <code>ctypes.</code><code>c_ubyte</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_ubyte</span></span>
: Represents the C <span class="xref c c-texpr">unsigned char</span> datatype, it interprets the value as small integer. The constructor accepts an optional integer initializer; no overflow checking is done.
+
: 表示 C <span class="xref c c-texpr">unsigned char</span> 数据类型,它将值解释为小整数。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
  
; ''class'' <code>ctypes.</code><code>c_uint</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_uint</span></span>
: Represents the C <span class="xref c c-texpr">unsigned int</span> datatype. The constructor accepts an optional integer initializer; no overflow checking is done. On platforms where <code>sizeof(int) == sizeof(long)</code> it is an alias for [[#ctypes.c_ulong|<code>c_ulong</code>]].
+
: 表示 C <span class="xref c c-texpr">unsigned int</span> 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。 在 <code>sizeof(int) == sizeof(long)</code> 它是 [[#ctypes.c_ulong|c_ulong]] 的别名的平台上。
  
; ''class'' <code>ctypes.</code><code>c_uint8</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_uint8</span></span>
: Represents the C 8-bit <span class="xref c c-texpr">unsigned int</span> datatype. Usually an alias for [[#ctypes.c_ubyte|<code>c_ubyte</code>]].
+
: 表示 C 8 <span class="xref c c-texpr">unsigned int</span> 数据类型。 通常是 [[#ctypes.c_ubyte|c_ubyte]] 的别名。
  
; ''class'' <code>ctypes.</code><code>c_uint16</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_uint16</span></span>
: Represents the C 16-bit <span class="xref c c-texpr">unsigned int</span> datatype. Usually an alias for [[#ctypes.c_ushort|<code>c_ushort</code>]].
+
: 表示 C 16 <span class="xref c c-texpr">unsigned int</span> 数据类型。 通常是 [[#ctypes.c_ushort|c_ushort]] 的别名。
  
; ''class'' <code>ctypes.</code><code>c_uint32</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_uint32</span></span>
: Represents the C 32-bit <span class="xref c c-texpr">unsigned int</span> datatype. Usually an alias for [[#ctypes.c_uint|<code>c_uint</code>]].
+
: 表示 C 32 <span class="xref c c-texpr">unsigned int</span> 数据类型。 通常是 [[#ctypes.c_uint|c_uint]] 的别名。
  
; ''class'' <code>ctypes.</code><code>c_uint64</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_uint64</span></span>
: Represents the C 64-bit <span class="xref c c-texpr">unsigned int</span> datatype. Usually an alias for [[#ctypes.c_ulonglong|<code>c_ulonglong</code>]].
+
: 表示 C 64 <span class="xref c c-texpr"> unsigned int</span> 数据类型。 通常是 [[#ctypes.c_ulonglong|c_ulonglong]] 的别名。
  
; ''class'' <code>ctypes.</code><code>c_ulong</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_ulong</span></span>
: Represents the C <span class="xref c c-texpr">unsigned long</span> datatype. The constructor accepts an optional integer initializer; no overflow checking is done.
+
: 表示 C <span class="xref c c-texpr"> unsigned long</span> 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
  
; ''class'' <code>ctypes.</code><code>c_ulonglong</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_ulonglong</span></span>
: Represents the C <span class="xref c c-texpr">unsigned long long</span> datatype. The constructor accepts an optional integer initializer; no overflow checking is done.
+
: 表示 C <span class="xref c c-texpr"> unsigned long long</span> 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
  
; ''class'' <code>ctypes.</code><code>c_ushort</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_ushort</span></span>
: Represents the C <span class="xref c c-texpr">unsigned short</span> datatype. The constructor accepts an optional integer initializer; no overflow checking is done.
+
: 表示 C <span class="xref c c-texpr"> unsigned short</span> 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
  
; ''class'' <code>ctypes.</code><code>c_void_p</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_void_p</span></span>
: Represents the C <span class="xref c c-texpr">void*</span> type. The value is represented as integer. The constructor accepts an optional integer initializer.
+
: 表示 C <span class="xref c c-texpr">void*</span> 类型。 该值表示为整数。 构造函数接受一个可选的整数初始值设定项。
  
; ''class'' <code>ctypes.</code><code>c_wchar</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_wchar</span></span>
: Represents the C <code>wchar_t</code> datatype, and interprets the value as a single character unicode string. The constructor accepts an optional string initializer, the length of the string must be exactly one character.
+
: 表示 C <code>wchar_t</code> 数据类型,并将值解释为单字符 unicode 字符串。 构造函数接受一个可选的字符串初始化器,字符串的长度必须正好是一个字符。
  
; ''class'' <code>ctypes.</code><code>c_wchar_p</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_wchar_p</span></span>
: Represents the C <span class="xref c c-texpr">wchar_t*</span> datatype, which must be a pointer to a zero-terminated wide character string. The constructor accepts an integer address, or a string.
+
: 表示 C <span class="xref c c-texpr">wchar_t*</span> 数据类型,它必须是指向以零结尾的宽字符串的指针。 构造函数接受一个整数地址或字符串。
  
; ''class'' <code>ctypes.</code><code>c_bool</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">c_bool</span></span>
: Represent the C <span class="xref c c-texpr">bool</span> datatype (more accurately, <span class="xref c c-texpr">_Bool</span> from C99). Its value can be <code>True</code> or <code>False</code>, and the constructor accepts any object that has a truth value.
+
: 表示 C <span class="xref c c-texpr">bool</span> 数据类型(更准确地说,是 C99 中的 <span class="xref c c-texpr">_Bool</span>)。 它的值可以是 <code>True</code> <code>False</code>,构造函数接受任何具有真值的对象。
  
; ''class'' <code>ctypes.</code><code>HRESULT</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">HRESULT</span></span>
: Windows only: Represents a <code>HRESULT</code> value, which contains success or error information for a function or method call.
+
: 仅限 Windows:表示 <code>HRESULT</code> 值,其中包含函数或方法调用的成功或错误信息。
  
; ''class'' <code>ctypes.</code><code>py_object</code>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">py_object</span></span>
: Represents the C <span class="xref c c-texpr">[[../../c-api/structures#c|PyObject]]*</span> datatype. Calling this without an argument creates a <code>NULL</code> <span class="xref c c-texpr">[[../../c-api/structures#c|PyObject]]*</span> pointer.
+
: 表示 C <span class="xref c c-texpr">PyObject*</span> 数据类型。 不带参数调用它会创建一个 <code>NULL</code> <span class="xref c c-texpr">PyObject*</span> 指针。
  
The <code>ctypes.wintypes</code> module provides quite some other Windows specific
+
<code>ctypes.wintypes</code> 模块提供了相当多的其他 Windows 特定数据类型,例如 <code>HWND</code><code>WPARAM</code> <code>DWORD</code>。 还定义了一些有用的结构,如 <code>MSG</code> <code>RECT</code>
data types, for example <code>HWND</code>, <code>WPARAM</code>, or <code>DWORD</code>. Some
 
useful structures like <code>MSG</code> or <code>RECT</code> are also defined.
 
  
  
第2,725行: 第2,232行:
  
 
<span id="ctypes-structured-data-types"></span>
 
<span id="ctypes-structured-data-types"></span>
=== Structured data types ===
+
=== 结构化数据类型 ===
  
; ''class'' <code>ctypes.</code><code>Union</code><span class="sig-paren">(</span>''<span class="o">*</span><span class="n">args</span>'', ''<span class="o">**</span><span class="n">kw</span>''<span class="sig-paren">)</span>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">Union</span></span><span class="sig-paren">(</span>''<span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">args</span></span>'', ''<span class="o"><span class="pre">**</span></span><span class="n"><span class="pre">kw</span></span>''<span class="sig-paren">)</span>
: Abstract base class for unions in native byte order.
+
: 本机字节顺序的联合的抽象基类。
  
; ''class'' <code>ctypes.</code><code>BigEndianStructure</code><span class="sig-paren">(</span>''<span class="o">*</span><span class="n">args</span>'', ''<span class="o">**</span><span class="n">kw</span>''<span class="sig-paren">)</span>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">BigEndianStructure</span></span><span class="sig-paren">(</span>''<span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">args</span></span>'', ''<span class="o"><span class="pre">**</span></span><span class="n"><span class="pre">kw</span></span>''<span class="sig-paren">)</span>
: Abstract base class for structures in ''big endian'' byte order.
+
: ''big endian'' 字节顺序结构的抽象基类。
  
; ''class'' <code>ctypes.</code><code>LittleEndianStructure</code><span class="sig-paren">(</span>''<span class="o">*</span><span class="n">args</span>'', ''<span class="o">**</span><span class="n">kw</span>''<span class="sig-paren">)</span>
+
; ''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">LittleEndianStructure</span></span><span class="sig-paren">(</span>''<span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">args</span></span>'', ''<span class="o"><span class="pre">**</span></span><span class="n"><span class="pre">kw</span></span>''<span class="sig-paren">)</span>
: Abstract base class for structures in ''little endian'' byte order.
+
: ''little endian'' 字节顺序结构的抽象基类。
  
Structures with non-native byte order cannot contain pointer type fields, or any
+
具有非本地字节顺序的结构不能包含指针类型字段,或包含指针类型字段的任何其他数据类型。
other data types containing pointer type fields.
 
  
 
<dl>
 
<dl>
<dt>''class'' <code>ctypes.</code><code>Structure</code><span class="sig-paren">(</span>''<span class="o">*</span><span class="n">args</span>'', ''<span class="o">**</span><span class="n">kw</span>''<span class="sig-paren">)</span></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">Structure</span></span><span class="sig-paren">(</span>''<span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">args</span></span>'', ''<span class="o"><span class="pre">**</span></span><span class="n"><span class="pre">kw</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Abstract base class for structures in ''native'' byte order.</p>
+
<dd><p>''native'' 字节顺序结构的抽象基类。</p>
<p>Concrete structure and union types must be created by subclassing one of these
+
<p>具体的结构和联合类型必须通过继承这些类型之一来创建,并且至少定义一个 [[#ctypes.Structure._fields_|_fields_]] 类变量。 [[#module-ctypes|ctypes]] 将创建 [[../../glossary#term-descriptor|描述符]] ,允许通过直接属性访问读取和写入字段。 这些是</p>
types, and at least define a [[#ctypes.Structure._fields_|<code>_fields_</code>]] class variable. [[#module-ctypes|<code>ctypes</code>]] will
 
create [[../../glossary#term-descriptor|<span class="xref std std-term">descriptor</span>]]s which allow reading and writing the fields by direct
 
attribute accesses. These are the</p>
 
 
<dl>
 
<dl>
<dt><code>_fields_</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">_fields_</span></span></dt>
<dd><p>A sequence defining the structure fields. The items must be 2-tuples or
+
<dd><p>定义结构字段的序列。 项必须是 2 元组或 3 元组。 第一项是字段名称,第二项指定字段类型; 它可以是任何 ctypes 数据类型。</p>
3-tuples. The first item is the name of the field, the second item
+
<p>对于像 [[#ctypes.c_int|c_int]] 这样的整数类型字段,可以给出第三个可选项。 它必须是一个小的正整数,用于定义字段的位宽。</p>
specifies the type of the field; it can be any ctypes data type.</p>
+
<p>字段名称在一个结构或联合中必须是唯一的。 未选中此项,当名称重复时,只能访问一个字段。</p>
<p>For integer type fields like [[#ctypes.c_int|<code>c_int</code>]], a third optional item can be
+
<p>可以在定义 Structure 子类的 class 语句之后定义 [[#ctypes.Structure._fields_|_fields_]] 类变量 ,这允许创建直接或间接引用自身的数据类型:</p>
given. It must be a small positive integer defining the bit width of the
 
field.</p>
 
<p>Field names must be unique within one structure or union. This is not
 
checked, only one field can be accessed when names are repeated.</p>
 
<p>It is possible to define the [[#ctypes.Structure._fields_|<code>_fields_</code>]] class variable ''after'' the
 
class statement that defines the Structure subclass, this allows creating
 
data types that directly or indirectly reference themselves:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>class List(Structure):
+
<syntaxhighlight lang="python3">class List(Structure):
 
     pass
 
     pass
List._fields_ = [(&quot;pnext&quot;, POINTER(List)),
+
List._fields_ = [("pnext", POINTER(List)),
 
                 ...
 
                 ...
                 ]</pre>
+
                 ]</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>The [[#ctypes.Structure._fields_|<code>_fields_</code>]] class variable must, however, be defined before the
+
<p>然而,[[#ctypes.Structure._fields_|_fields_]] 类变量必须在第一次使用类型之前定义(创建一个实例,在它上面调用 [[#ctypes.sizeof|sizeof()]],等等)。 稍后对 [[#ctypes.Structure._fields_|_fields_]] 类变量的赋值将引发 AttributeError。</p>
type is first used (an instance is created, [[#ctypes.sizeof|<code>sizeof()</code>]] is called on it,
+
<p>可以定义结构类型的子子类,它们继承基类的字段加上子子类中定义的 [[#ctypes.Structure._fields_|_fields_]](如果有)。</p></dd></dl>
and so on). Later assignments to the [[#ctypes.Structure._fields_|<code>_fields_</code>]] class variable will
 
raise an AttributeError.</p>
 
<p>It is possible to define sub-subclasses of structure types, they inherit
 
the fields of the base class plus the [[#ctypes.Structure._fields_|<code>_fields_</code>]] defined in the
 
sub-subclass, if any.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>_pack_</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">_pack_</span></span></dt>
<dd><p>An optional small integer that allows overriding the alignment of
+
<dd><p>一个可选的小整数,允许覆盖实例中结构字段的对齐方式。 [[#ctypes.Structure._pack_|_pack_]] 必须在分配 [[#ctypes.Structure._fields_|_fields_]] 时已经定义,否则无效。</p></dd></dl>
structure fields in the instance. [[#ctypes.Structure._pack_|<code>_pack_</code>]] must already be defined
 
when [[#ctypes.Structure._fields_|<code>_fields_</code>]] is assigned, otherwise it will have no effect.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>_anonymous_</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">_anonymous_</span></span></dt>
<dd><p>An optional sequence that lists the names of unnamed (anonymous) fields.
+
<dd><p>列出未命名(匿名)字段名称的可选序列。 [[#ctypes.Structure._anonymous_|_anonymous_]] 必须在分配[[#ctypes.Structure._fields_|_fields_]] 时已经定义,否则无效。</p>
[[#ctypes.Structure._anonymous_|<code>_anonymous_</code>]] must be already defined when [[#ctypes.Structure._fields_|<code>_fields_</code>]] is
+
<p>此变量中列出的字段必须是结构或联合类型字段。 [[#module-ctypes|ctypes]] 将在允许直接访问嵌套字段的结构类型中创建描述符,而无需创建结构或联合字段。</p>
assigned, otherwise it will have no effect.</p>
+
<p>这是一个示例类型(Windows):</p>
<p>The fields listed in this variable must be structure or union type fields.
 
[[#module-ctypes|<code>ctypes</code>]] will create descriptors in the structure type that allows
 
accessing the nested fields directly, without the need to create the
 
structure or union field.</p>
 
<p>Here is an example type (Windows):</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>class _U(Union):
+
<syntaxhighlight lang="python3">class _U(Union):
     _fields_ = [(&quot;lptdesc&quot;, POINTER(TYPEDESC)),
+
     _fields_ = [("lptdesc", POINTER(TYPEDESC)),
                 (&quot;lpadesc&quot;, POINTER(ARRAYDESC)),
+
                 ("lpadesc", POINTER(ARRAYDESC)),
                 (&quot;hreftype&quot;, HREFTYPE)]
+
                 ("hreftype", HREFTYPE)]
  
 
class TYPEDESC(Structure):
 
class TYPEDESC(Structure):
     _anonymous_ = (&quot;u&quot;,)
+
     _anonymous_ = ("u",)
     _fields_ = [(&quot;u&quot;, _U),
+
     _fields_ = [("u", _U),
                 (&quot;vt&quot;, VARTYPE)]</pre>
+
                 ("vt", VARTYPE)]</syntaxhighlight>
  
 
</div>
 
</div>
  
 
</div>
 
</div>
<p>The <code>TYPEDESC</code> structure describes a COM data type, the <code>vt</code> field
+
<p><code>TYPEDESC</code> 结构描述了一种 COM 数据类型,<code>vt</code> 字段指定哪一个联合字段是有效的。 由于 <code>u</code> 字段被定义为匿名字段,现在可以直接从 TYPEDESC 实例访问成员。 <code>td.lptdesc</code> <code>td.u.lptdesc</code> 是等价的,但前者更快,因为它不需要创建临时联合实例:</p>
specifies which one of the union fields is valid. Since the <code>u</code> field
 
is defined as anonymous field, it is now possible to access the members
 
directly off the TYPEDESC instance. <code>td.lptdesc</code> and <code>td.u.lptdesc</code>
 
are equivalent, but the former is faster since it does not need to create
 
a temporary union instance:</p>
 
 
<div class="highlight-python3 notranslate">
 
<div class="highlight-python3 notranslate">
  
 
<div class="highlight">
 
<div class="highlight">
  
<pre>td = TYPEDESC()
+
<syntaxhighlight lang="python3">td = TYPEDESC()
 
td.vt = VT_PTR
 
td.vt = VT_PTR
 
td.lptdesc = POINTER(some_type)
 
td.lptdesc = POINTER(some_type)
td.u.lptdesc = POINTER(some_type)</pre>
+
td.u.lptdesc = POINTER(some_type)</syntaxhighlight>
  
 
</div>
 
</div>
第2,832行: 第2,311行:
 
</div></dd></dl>
 
</div></dd></dl>
  
<p>It is possible to define sub-subclasses of structures, they inherit the
+
<p>可以定义结构的子子类,它们继承基类的字段。 如果子类定义具有单独的 [[#ctypes.Structure._fields_|_fields_]] 变量,则在此指定的字段将附加到基类的字段。</p>
fields of the base class. If the subclass definition has a separate
+
<p>结构和联合构造函数接受位置参数和关键字参数。 位置参数用于按照它们出现在 [[#ctypes.Structure._fields_|_fields_]] 中的相同顺序初始化成员字段。 构造函数中的关键字参数被解释为属性赋值,因此它们将使用相同的名称初始化 [[#ctypes.Structure._fields_|_fields_]],或者为 [[#ctypes.Structure._fields_|_fields_]] 中不存在的名称创建新属性。</p></dd></dl>
[[#ctypes.Structure._fields_|<code>_fields_</code>]] variable, the fields specified in this are appended to the
 
fields of the base class.</p>
 
<p>Structure and union constructors accept both positional and keyword
 
arguments. Positional arguments are used to initialize member fields in the
 
same order as they are appear in [[#ctypes.Structure._fields_|<code>_fields_</code>]]. Keyword arguments in the
 
constructor are interpreted as attribute assignments, so they will initialize
 
[[#ctypes.Structure._fields_|<code>_fields_</code>]] with the same name, or create new attributes for names not
 
present in [[#ctypes.Structure._fields_|<code>_fields_</code>]].</p></dd></dl>
 
  
  
第2,848行: 第2,319行:
  
 
<span id="ctypes-arrays-pointers"></span>
 
<span id="ctypes-arrays-pointers"></span>
=== Arrays and pointers ===
+
=== 数组和指针 ===
  
 
<dl>
 
<dl>
<dt>''class'' <code>ctypes.</code><code>Array</code><span class="sig-paren">(</span>''\*args''<span class="sig-paren">)</span></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">Array</span></span><span class="sig-paren">(</span>''<span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">args</span></span>''<span class="sig-paren">)</span></dt>
<dd><p>Abstract base class for arrays.</p>
+
<dd><p>数组的抽象基类。</p>
<p>The recommended way to create concrete array types is by multiplying any
+
<p>创建具体数组类型的推荐方法是将任何 [[#module-ctypes|ctypes]] 数据类型乘以一个正整数。 或者,您可以子类化此类型并定义 [[#ctypes.Array._length_|_length_]] [[#ctypes.Array._type_|_type_]] 类变量。 可以使用标准下标和切片访问来读取和写入数组元素; 对于切片读取,结果对象是 ''不是'' 本身是 [[#ctypes.Array|数组]] </p>
[[#module-ctypes|<code>ctypes</code>]] data type with a positive integer. Alternatively, you can subclass
 
this type and define [[#ctypes.Array._length_|<code>_length_</code>]] and [[#ctypes.Array._type_|<code>_type_</code>]] class variables.
 
Array elements can be read and written using standard
 
subscript and slice accesses; for slice reads, the resulting object is
 
''not'' itself an [[#ctypes.Array|<code>Array</code>]].</p>
 
 
<dl>
 
<dl>
<dt><code>_length_</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">_length_</span></span></dt>
<dd><p>A positive integer specifying the number of elements in the array.
+
<dd><p>一个正整数,指定数组中的元素数。 超出范围的下标会导致 [[../exceptions#IndexError|IndexError]]。 将由 [[../functions#len|len()]] 返回。</p></dd></dl>
Out-of-range subscripts result in an [[../exceptions#IndexError|<code>IndexError</code>]]. Will be
 
returned by [[../functions#len|<code>len()</code>]].</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt><code>_type_</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">_type_</span></span></dt>
<dd><p>Specifies the type of each element in the array.</p></dd></dl>
+
<dd><p>指定数组中每个元素的类型。</p></dd></dl>
  
<p>Array subclass constructors accept positional arguments, used to
+
<p>数组子类构造函数接受位置参数,用于按顺序初始化元素。</p></dd></dl>
initialize the elements in order.</p></dd></dl>
 
  
 
<dl>
 
<dl>
<dt>''class'' <code>ctypes.</code><code>_Pointer</code></dt>
+
<dt>''<span class="pre">class</span>'' <span class="sig-prename descclassname"><span class="pre">ctypes.</span></span><span class="sig-name descname"><span class="pre">_Pointer</span></span></dt>
<dd><p>Private, abstract base class for pointers.</p>
+
<dd><p>指针的私有抽象基类。</p>
<p>Concrete pointer types are created by calling [[#ctypes.POINTER|<code>POINTER()</code>]] with the
+
<p>具体的指针类型是通过使用将要指向的类型调用 [[#ctypes.POINTER|POINTER()]] 来创建的; 这是由 [[#ctypes.pointer|pointer()]] 自动完成的。</p>
type that will be pointed to; this is done automatically by
+
<p>如果指针指向数组,则可以使用标准下标和切片访问读取和写入其元素。 指针对象没有大小,因此 [[../functions#len|len()]] 将引发 [[../exceptions#TypeError|TypeError]]。 负下标将在 ''之前从内存中读取'' 指针(如在 C 中),超出范围的下标可能会因访问冲突而崩溃(如果你很幸运)。</p>
[[#ctypes.pointer|<code>pointer()</code>]].</p>
 
<p>If a pointer points to an array, its elements can be read and
 
written using standard subscript and slice accesses. Pointer objects
 
have no size, so [[../functions#len|<code>len()</code>]] will raise [[../exceptions#TypeError|<code>TypeError</code>]]. Negative
 
subscripts will read from the memory ''before'' the pointer (as in C), and
 
out-of-range subscripts will probably crash with an access violation (if
 
you're lucky).</p>
 
 
<dl>
 
<dl>
<dt><code>_type_</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">_type_</span></span></dt>
<dd><p>Specifies the type pointed to.</p></dd></dl>
+
<dd><p>指定指向的类型。</p></dd></dl>
  
 
<dl>
 
<dl>
<dt><code>contents</code></dt>
+
<dt><span class="sig-name descname"><span class="pre">contents</span></span></dt>
<dd><p>Returns the object to which to pointer points. Assigning to this
+
<dd><p>返回指针指向的对象。 分配给该属性会将指针更改为指向所分配的对象。</p></dd></dl>
attribute changes the pointer to point to the assigned object.</p></dd></dl>
 
 
</dd></dl>
 
</dd></dl>
  
第2,898行: 第2,353行:
  
 
</div>
 
</div>
 +
 +
</div>
 +
<div class="clearer">
 +
 +
  
 
</div>
 
</div>
  
[[Category:Python 3.9 中文文档]]
+
[[Category:Python 3.9 文档]]

2021年10月31日 (日) 04:51的最新版本

ctypes — Python 的外部函数库


ctypes 是 Python 的外部函数库。 它提供与 C 兼容的数据类型,并允许调用 DLL 或共享库中的函数。 它可用于将这些库包装在纯 Python 中。

ctypes教程

注意:本教程中的代码示例使用 doctest 来确保它们确实有效。 由于某些代码示例在 Linux、Windows 或 macOS 下的行为不同,因此它们在注释中包含 doctest 指令。

注意:一些代码示例引用了 ctypes c_int 类型。 在 sizeof(long) == sizeof(int) 它是 c_long 的别名的平台上。 因此,如果您期望 c_int 打印 c_long,您不应该感到困惑——它们实际上是相同的类型。

从加载的 dll 访问函数

函数作为 dll 对象的属性被访问:

>>> from ctypes import *
>>> libc.printf
<_FuncPtr object at 0x...>
>>> print(windll.kernel32.GetModuleHandleA)  
<_FuncPtr object at 0x...>
>>> print(windll.kernel32.MyOwnFunction)     
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "ctypes.py", line 239, in __getattr__
    func = _StdcallFuncPtr(name, self)
AttributeError: function 'MyOwnFunction' not found
>>>

请注意,像 kernel32user32 这样的 win32 系统 dll 通常会导出函数的 ANSI 和 UNICODE 版本。 UNICODE 版本在导出时在名称后附加了 W,而 ANSI 版本在导出时在名称后附加了 A。 win32 GetModuleHandle 函数返回给定模块名称的 模块句柄 ,具有以下 C 原型,并使用宏将其中之一公开为 GetModuleHandle取决于是否定义了 UNICODE:

/* ANSI version */
HMODULE GetModuleHandleA(LPCSTR lpModuleName);
/* UNICODE version */
HMODULE GetModuleHandleW(LPCWSTR lpModuleName);

windll 不会尝试通过魔法选择其中之一,您必须通过显式指定 GetModuleHandleAGetModuleHandleW 来访问您需要的版本,然后用字节或字符串调用它对象分别。

有时,dll 导出的函数名称不是有效的 Python 标识符,例如 "??2@YAPAXI@Z"。 在这种情况下,您必须使用 getattr() 来检索函数:

>>> getattr(cdll.msvcrt, "??2@YAPAXI@Z")  
<_FuncPtr object at 0x...>
>>>

在 Windows 上,一些 dll 不是按名称而是按顺序导出函数。 可以通过使用序号索引 dll 对象来访问这些函数:

>>> cdll.kernel32[1]  
<_FuncPtr object at 0x...>
>>> cdll.kernel32[0]  
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "ctypes.py", line 310, in __getitem__
    func = _StdcallFuncPtr(name, self)
AttributeError: function ordinal 0 not found
>>>

调用函数

您可以像调用任何其他 Python 可调用函数一样调用这些函数。 此示例使用 time() 函数,该函数返回自 Unix 纪元以来以秒为单位的系统时间,以及 GetModuleHandleA() 函数,该函数返回一个 win32 模块句柄。

此示例使用 NULL 指针调用这两个函数(None 应用作 NULL 指针):

>>> print(libc.time(None))  
1150640792
>>> print(hex(windll.kernel32.GetModuleHandleA(None)))  
0x1d000000
>>>

当您使用 cdecl 调用约定调用 stdcall 函数时,会引发 ValueError,反之亦然:

>>> cdll.kernel32.GetModuleHandleA(None)  
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
>>>

>>> windll.msvcrt.printf(b"spam")  
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
>>>

要找出正确的调用约定,您必须查看 C 头文件或要调用的函数的文档。

在 Windows 上,ctypes 使用 win32 结构化异常处理来防止在使用无效参数值调用函数时由于一般保护错误而导致崩溃:

>>> windll.kernel32.GetModuleHandleA(32)  
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: exception: access violation reading 0x00000020
>>>

然而,有足够的方法可以使 Python 与 ctypes 崩溃,所以无论如何你都应该小心。 faulthandler 模块有助于调试崩溃(例如 由错误的 C 库调用产生的分段错误)。

None、整数、字节对象和(unicode)字符串是唯一可以在这些函数调用中直接用作参数的原生 Python 对象。 None 作为 C NULL 指针传递,字节对象和字符串作为指向包含其数据的内存块的指针传递(char*wchar_t* )。 Python 整数作为平台默认的 C int 类型传递,它们的值被屏蔽以适应 C 类型。

在继续使用其他参数类型调用函数之前,我们必须了解更多关于 ctypes 数据类型的信息。


基本数据类型

ctypes 定义了一些原始的 C 兼容数据类型:

ctypes 类型 C型 蟒蛇型
c_bool _布尔 布尔 (1)
c_char 字符 1 个字符的字节对象
c_wchar wchar_t 1 个字符的字符串
c_byte 字符 整数
c_ubyte 无符号的字符 整数
c_short 短的 整数
c_ushort 无符号短 整数
c_int 整数 整数
c_uint 无符号整数 整数
c_long 整数
c_ulong 无符号长 整数
c_longlong __int64长长 整数
c_ulonglong unsigned __int64unsigned long long 整数
c_size_t size_t 整数
c_ssize_t ssize_tPy_ssize_t 整数
c_float 漂浮 漂浮
c_double 双倍的 漂浮
c_longdouble 长双 漂浮
c_char_p char*(NUL 终止) 字节对象或 None
c_wchar_p wchar_t*(NUL 终止) 字符串或 None
c_void_p 空白* 整数或 None
  1. 构造函数接受任何具有真值的对象。

所有这些类型都可以通过使用正确类型和值的可选初始化程序调用它们来创建:

>>> c_int()
c_long(0)
>>> c_wchar_p("Hello, World")
c_wchar_p(140018365411392)
>>> c_ushort(-3)
c_ushort(65533)
>>>

由于这些类型是可变的,它们的值也可以在之后更改:

>>> i = c_int(42)
>>> print(i)
c_long(42)
>>> print(i.value)
42
>>> i.value = -99
>>> print(i.value)
-99
>>>

为指针类型 c_char_pc_wchar_pc_void_p 的实例分配一个新值会改变它们指向的 内存位置]不是内存块的内容(当然不是,因为Python字节对象是不可变的):

>>> s = "Hello, World"
>>> c_s = c_wchar_p(s)
>>> print(c_s)
c_wchar_p(139966785747344)
>>> print(c_s.value)
Hello World
>>> c_s.value = "Hi, there"
>>> print(c_s)              # the memory location has changed
c_wchar_p(139966783348904)
>>> print(c_s.value)
Hi, there
>>> print(s)                # first object is unchanged
Hello, World
>>>

但是,您应该小心,不要将它们传递给需要指向可变内存的指针的函数。 如果您需要可变内存块,ctypes 有一个 create_string_buffer() 函数,它以各种方式创建这些。 可以使用 raw 属性访问(或更改)当前内存块内容; 如果要以 NUL 终止的字符串形式访问它,请使用 value 属性:

>>> from ctypes import *
>>> p = create_string_buffer(3)            # create a 3 byte buffer, initialized to NUL bytes
>>> print(sizeof(p), repr(p.raw))
3 b'\x00\x00\x00'
>>> p = create_string_buffer(b"Hello")     # create a buffer containing a NUL terminated string
>>> print(sizeof(p), repr(p.raw))
6 b'Hello\x00'
>>> print(repr(p.value))
b'Hello'
>>> p = create_string_buffer(b"Hello", 10) # create a 10 byte buffer
>>> print(sizeof(p), repr(p.raw))
10 b'Hello\x00\x00\x00\x00\x00'
>>> p.value = b"Hi"
>>> print(sizeof(p), repr(p.raw))
10 b'Hi\x00lo\x00\x00\x00\x00\x00'
>>>

create_string_buffer() 函数替换了 c_buffer() 函数(仍可用作别名),以及早期 ctypes 版本中的 c_string() 函数。 要创建包含 C 类型 wchar_t Unicode 字符的可变内存块,请使用 create_unicode_buffer() 函数。


调用函数,续

请注意,printf 打印到真正的标准输出通道,notsys.stdout,因此这些示例仅适用于控制台提示符,而不适用于 IDLEPythonWin

>>> printf = libc.printf
>>> printf(b"Hello, %s\n", b"World!")
Hello, World!
14
>>> printf(b"Hello, %S\n", "World!")
Hello, World!
14
>>> printf(b"%d bottles of beer\n", 42)
42 bottles of beer
19
>>> printf(b"%f bottles of beer\n", 42.5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ArgumentError: argument 2: exceptions.TypeError: Don't know how to convert parameter 2
>>>

如前所述,除整数、字符串和字节对象之外的所有 Python 类型都必须包装在其对应的 ctypes 类型中,以便将它们转换为所需的 C 数据类型:

>>> printf(b"An int %d, a double %f\n", 1234, c_double(3.14))
An int 1234, a double 3.140000
31
>>>

使用您自己的自定义数据类型调用函数

您还可以自定义 ctypes 参数转换,以允许将您自己的类的实例用作函数参数。 ctypes 查找 _as_parameter_ 属性并将其用作函数参数。 当然,它必须是整数、字符串或字节之一:

>>> class Bottles:
...     def __init__(self, number):
...         self._as_parameter_ = number
...
>>> bottles = Bottles(42)
>>> printf(b"%d bottles of beer\n", bottles)
42 bottles of beer
19
>>>

如果您不想将实例的数据存储在 _as_parameter_ 实例变量中,您可以定义一个 属性 ,使该属性在请求时可用。


指定所需的参数类型(函数原型)

可以通过设置 argtypes 属性来指定从 DLL 导出的函数所需的参数类型。

argtypes 必须是 C 数据类型的序列(printf 函数在这里可能不是一个很好的例子,因为它根据格式字符串需要一个变量数和不同类型的参数,在另一方面,这对于试验此功能非常方便):

>>> printf.argtypes = [c_char_p, c_char_p, c_int, c_double]
>>> printf(b"String '%s', Int %d, Double %f\n", b"Hi", 10, 2.2)
String 'Hi', Int 10, Double 2.200000
37
>>>

指定格式可以防止不兼容的参数类型(就像 C 函数的原型一样),并尝试将参数转换为有效类型:

>>> printf(b"%d %d %d", 1, 2, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ArgumentError: argument 2: exceptions.TypeError: wrong type
>>> printf(b"%s %d %f\n", b"X", 2, 3)
X 2 3.000000
13
>>>

如果您定义了自己的类并传递给函数调用,则必须实现一个 from_param() 类方法,以便它们能够在 argtypes 序列中使用它们。 from_param() 类方法接收传递给函数调用的 Python 对象,它应该进行类型检查或任何需要以确保该对象是可接受的,然后返回对象本身,它的 _as_parameter_属性,或者在这种情况下您想作为 C 函数参数传递的任何内容。 同样,结果应该是整数、字符串、字节、ctypes 实例或具有 _as_parameter_ 属性的对象。


返回类型

默认情况下,函数假定返回 C int 类型。 其他返回类型可以通过设置函数对象的restype属性来指定。

这是一个更高级的例子,它使用 strchr 函数,它需要一个字符串指针和一个字符,并返回一个指向字符串的指针:

>>> strchr = libc.strchr
>>> strchr(b"abcdef", ord("d"))  
8059983
>>> strchr.restype = c_char_p    # c_char_p is a pointer to a string
>>> strchr(b"abcdef", ord("d"))
b'def'
>>> print(strchr(b"abcdef", ord("x")))
None
>>>

如果要避免上面的 ord("x") 调用,可以设置 argtypes 属性,第二个参数将从单个字符的 Python 字节对象转换为 C 字符:

>>> strchr.restype = c_char_p
>>> strchr.argtypes = [c_char_p, c_char]
>>> strchr(b"abcdef", b"d")
'def'
>>> strchr(b"abcdef", b"def")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ArgumentError: argument 2: exceptions.TypeError: one character string expected
>>> print(strchr(b"abcdef", b"x"))
None
>>> strchr(b"abcdef", b"d")
'def'
>>>

如果外部函数返回整数,您还可以使用可调用的 Python 对象(例如函数或类)作为 restype 属性。 将使用 C 函数返回的 整数 调用可调用对象,并且此调用的结果将用作函数调用的结果。 这对于检查错误返回值并自动引发异常很有用:

>>> GetModuleHandle = windll.kernel32.GetModuleHandleA  
>>> def ValidHandle(value):
...     if value == 0:
...         raise WinError()
...     return value
...
>>>
>>> GetModuleHandle.restype = ValidHandle  
>>> GetModuleHandle(None)  
486539264
>>> GetModuleHandle("something silly")  
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in ValidHandle
OSError: [Errno 126] The specified module could not be found.
>>>

WinError 是一个函数,它将调用 Windows FormatMessage() api 来获取错误代码的字符串表示,而 返回 异常。 WinError 带有一个可选的错误代码参数,如果没有使用它,它会调用 GetLastError() 来检索它。

请注意,通过 errcheck 属性可以使用更强大的错误检查机制; 有关详细信息,请参阅参考手册。


传递指针(或:通过引用传递参数)

有时一个 C api 函数需要一个指向数据类型的 指针 作为参数,可能是写入相应的位置,或者如果数据太大而无法通过值传递。 这也称为 通过引用 传递参数。

ctypes 导出 byref() 函数,用于通过引用传递参数。 使用pointer()函数也可以达到同样的效果,虽然pointer()做了很多工作,因为它构造了一个真正的指针对象,所以使用速度更快]byref() 如果你不需要 Python 本身的指针对象:

>>> i = c_int()
>>> f = c_float()
>>> s = create_string_buffer(b'\000' * 32)
>>> print(i.value, f.value, repr(s.value))
0 0.0 b''
>>> libc.sscanf(b"1 3.14 Hello", b"%d %f %s",
...             byref(i), byref(f), s)
3
>>> print(i.value, f.value, repr(s.value))
1 3.1400001049 b'Hello'
>>>

结构和工会

结构和联合必须从 ctypes 模块中定义的 StructureUnion 基类派生。 每个子类必须定义一个 _fields_ 属性。 _fields_ 必须是 2 元组 的列表,包含 字段名称字段类型

字段类型必须是 ctypes 类型,如 c_int,或任何其他派生的 ctypes 类型:结构、联合、数组、指针。

下面是一个简单的 POINT 结构示例,其中包含两个名为 xy 的整数,并且还展示了如何在构造函数中初始化结构:

>>> from ctypes import *
>>> class POINT(Structure):
...     _fields_ = [("x", c_int),
...                 ("y", c_int)]
...
>>> point = POINT(10, 20)
>>> print(point.x, point.y)
10 20
>>> point = POINT(y=5)
>>> print(point.x, point.y)
0 5
>>> POINT(1, 2, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: too many initializers
>>>

但是,您可以构建更复杂的结构。 通过将结构用作字段类型,结构本身可以包含其他结构。

这是一个 RECT 结构,它包含两个名为 upperleftlowerright 的 POINT:

>>> class RECT(Structure):
...     _fields_ = [("upperleft", POINT),
...                 ("lowerright", POINT)]
...
>>> rc = RECT(point)
>>> print(rc.upperleft.x, rc.upperleft.y)
0 5
>>> print(rc.lowerright.x, rc.lowerright.y)
0 0
>>>

嵌套结构也可以通过以下几种方式在构造函数中初始化:

>>> r = RECT(POINT(1, 2), POINT(3, 4))
>>> r = RECT((1, 2), (3, 4))

字段 描述符 可以从 中检索,它们对调试很有用,因为它们可以提供有用的信息:

>>> print(POINT.x)
<Field type=c_long, ofs=0, size=4>
>>> print(POINT.y)
<Field type=c_long, ofs=4, size=4>
>>>

警告

ctypes 不支持将带有位域的联合或结构按值传递给函数。 虽然这可能适用于 32 位 x86,但库不保证在一般情况下工作。 具有位域的联合和结构应始终通过指针传递给函数。


结构/联合对齐和字节顺序

默认情况下,Structure 和 Union 字段的对齐方式与 C 编译器的对齐方式相同。 可以通过在子类定义中指定 _pack_ 类属性来覆盖此行为。 这必须设置为正整数并指定字段的最大对齐方式。 这也是 #pragma pack(n) 在 MSVC 中所做的。

ctypes 使用结构和联合的本机字节顺序。 要构建具有非本机字节顺序的结构,您可以使用 BigEndianStructureLittleEndianStructureBigEndianUnionLittleEndianUnion 基类之一。 这些类不能包含指针字段。


结构体和联合体中的位域

可以创建包含位域的结构和联合。 位域仅适用于整数域,位宽被指定为 _fields_ 元组中的第三项:

>>> class Int(Structure):
...     _fields_ = [("first_16", c_int, 16),
...                 ("second_16", c_int, 16)]
...
>>> print(Int.first_16)
<Field type=c_long, ofs=0:0, bits=16>
>>> print(Int.second_16)
<Field type=c_long, ofs=0:16, bits=16>
>>>

数组

数组是序列,包含固定数量的相同类型的实例。

创建数组类型的推荐方法是将数据类型与正整数相乘:

TenPointsArrayType = POINT * 10

这是一个有点人为的数据类型的示例,该结构包含 4 个 POINT 以及其他内容:

>>> from ctypes import *
>>> class POINT(Structure):
...     _fields_ = ("x", c_int), ("y", c_int)
...
>>> class MyStruct(Structure):
...     _fields_ = [("a", c_int),
...                 ("b", c_float),
...                 ("point_array", POINT * 4)]
>>>
>>> print(len(MyStruct().point_array))
4
>>>

实例以通常的方式创建,通过调用类:

arr = TenPointsArrayType()
for pt in arr:
    print(pt.x, pt.y)

上面的代码打印了一系列 0 0 行,因为数组内容被初始化为零。

还可以指定正确类型的初始化程序:

>>> from ctypes import *
>>> TenIntegers = c_int * 10
>>> ii = TenIntegers(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
>>> print(ii)
<c_long_Array_10 object at 0x...>
>>> for i in ii: print(i, end=" ")
...
1 2 3 4 5 6 7 8 9 10
>>>

指针

指针实例是通过在 ctypes 类型上调用 pointer() 函数来创建的:

>>> from ctypes import *
>>> i = c_int(42)
>>> pi = pointer(i)
>>>

指针实例有一个 contents 属性,它返回指针指向的对象,上面的 i 对象:

>>> pi.contents
c_long(42)
>>>

请注意, ctypes 没有 OOR(原始对象返回),每次检索属性时它都会构造一个新的等效对象:

>>> pi.contents is i
False
>>> pi.contents is pi.contents
False
>>>

将另一个 c_int 实例分配给指针的内容属性会导致指针指向存储它的内存位置:

>>> i = c_int(99)
>>> pi.contents = i
>>> pi.contents
c_long(99)
>>>

指针实例也可以用整数索引:

>>> pi[0]
99
>>>

分配给整数索引会更改指向的值:

>>> print(i)
c_long(99)
>>> pi[0] = 22
>>> print(i)
c_long(22)
>>>

也可以使用不同于 0 的索引,但您必须知道自己在做什么,就像在 C 中一样:您可以访问或更改任意内存位置。 通常,如果您从 C 函数接收指针,并且您 知道 该指针实际上指向一个数组而不是单个项目,则您只会使用此功能。

在幕后,pointer() 函数不仅仅是创建指针实例,它还必须首先创建指针 types。 这是通过 POINTER() 函数完成的,该函数接受任何 ctypes 类型,并返回一个新类型:

>>> PI = POINTER(c_int)
>>> PI
<class 'ctypes.LP_c_long'>
>>> PI(42)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected c_long instead of int
>>> PI(c_int(42))
<ctypes.LP_c_long object at 0x...>
>>>

不带参数调用指针类型会创建一个 NULL 指针。 NULL 指针有一个 False 布尔值:

>>> null_ptr = POINTER(c_int)()
>>> print(bool(null_ptr))
False
>>>

ctypes 在解引用指针时检查 NULL(但解引用无效的非 NULL 指针会使 Python 崩溃):

>>> null_ptr[0]
Traceback (most recent call last):
    ....
ValueError: NULL pointer access
>>>

>>> null_ptr[0] = 1234
Traceback (most recent call last):
    ....
ValueError: NULL pointer access
>>>

类型转换

通常,ctypes 会进行严格的类型检查。 这意味着,如果在函数的 argtypes 列表中有 POINTER(c_int) 或作为结构定义中成员字段的类型,则只接受完全相同类型的实例。 此规则有一些例外,其中 ctypes 接受其他对象。 例如,您可以传递兼容的数组实例而不是指针类型。 因此,对于 POINTER(c_int),ctypes 接受一个 c_int 数组:

>>> class Bar(Structure):
...     _fields_ = [("count", c_int), ("values", POINTER(c_int))]
...
>>> bar = Bar()
>>> bar.values = (c_int * 3)(1, 2, 3)
>>> bar.count = 3
>>> for i in range(bar.count):
...     print(bar.values[i])
...
1
2
3
>>>

此外,如果函数参数在 argtypes 中显式声明为指针类型(例如 POINTER(c_int)),则为指向类型的对象(在本例中为 c_int)可以传递给函数。 在这种情况下,ctypes 将自动应用所需的 byref() 转换。

要将 POINTER 类型字段设置为 NULL,您可以分配 None

>>> bar.values = None
>>>

有时您有不兼容类型的实例。 在 C 中,您可以将一种类型转换为另一种类型。 ctypes 提供了一个 cast() 函数,可以以同样的方式使用。 上面定义的 Bar 结构接受 POINTER(c_int) 指针或 c_int 数组作为其 values 字段,但不接受其他类型的实例:

>>> bar.values = (c_byte * 4)()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: incompatible types, c_byte_Array_4 instance instead of LP_c_long instance
>>>

对于这些情况,cast() 函数很方便。

cast() 函数可用于将 ctypes 实例转换为指向不同 ctypes 数据类型的指针。 cast() 接受两个参数,一个是或可以转换为某种指针的 ctypes 对象,以及一个 ctypes 指针类型。 它返回第二个参数的实例,它引用与第一个参数相同的内存块:

>>> a = (c_byte * 4)()
>>> cast(a, POINTER(c_int))
<ctypes.LP_c_long object at ...>
>>>

因此,可以使用 cast() 将结构体分配给 Barvalues 字段:

>>> bar = Bar()
>>> bar.values = cast((c_byte * 4)(), POINTER(c_int))
>>> print(bar.values[0])
0
>>>

不完全类型

不完整类型 是结构、联合或数组,其成员尚未指定。 在 C 中,它们由前向声明指定,稍后定义:

struct cell; /* forward declaration */

struct cell {
    char *name;
    struct cell *next;
};

直接转换为 ctypes 代码是这样的,但它不起作用:

>>> class cell(Structure):
...     _fields_ = [("name", c_char_p),
...                 ("next", POINTER(cell))]
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in cell
NameError: name 'cell' is not defined
>>>

因为新的 class cell 在 class 语句本身中不可用。 在 ctypes 中,我们可以定义 cell 类,然后在 class 语句之后设置 _fields_ 属性:

>>> from ctypes import *
>>> class cell(Structure):
...     pass
...
>>> cell._fields_ = [("name", c_char_p),
...                  ("next", POINTER(cell))]
>>>

让我们试试吧。 我们创建了两个 cell 的实例,并让它们相互指向,最后沿着指针链走几次:

>>> c1 = cell()
>>> c1.name = b"foo"
>>> c2 = cell()
>>> c2.name = b"bar"
>>> c1.next = pointer(c2)
>>> c2.next = pointer(c1)
>>> p = c1
>>> for i in range(8):
...     print(p.name, end=" ")
...     p = p.next[0]
...
foo bar foo bar foo bar foo bar
>>>

回调函数

ctypes 允许从 Python 可调用对象创建 C 可调用函数指针。 这些有时称为 回调函数

首先,您必须为回调函数创建一个类。 该类知道调用约定、返回类型以及此函数将接收的参数的数量和类型。

CFUNCTYPE() 工厂函数使用 cdecl 调用约定为回调函数创建类型。 在 Windows 上,WINFUNCTYPE() 工厂函数使用 stdcall 调用约定为回调函数创建类型。

这两个工厂函数都以结果类型作为第一个参数被调用,回调函数期望的参数类型作为剩余的参数。

我将在此处展示一个示例,该示例使用标准 C 库的 qsort() 函数,该函数用于在回调函数的帮助下对项目进行排序。 qsort() 将用于对整数数组进行排序:

>>> IntArray5 = c_int * 5
>>> ia = IntArray5(5, 1, 7, 33, 99)
>>> qsort = libc.qsort
>>> qsort.restype = None
>>>

qsort() 必须使用指向要排序的数据的指针、数据数组中的项数、一项的大小以及指向比较函数、回调的指针来调用。 然后将使用两个指向项目的指针调用回调,如果第一个项目小于第二个项目,则它必须返回一个负整数,如果它们相等,则返回零,否则返回一个正整数。

所以我们的回调函数接收指向整数的指针,并且必须返回一个整数。 首先我们为回调函数创建type

>>> CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
>>>

首先,这是一个简单的回调,显示它传递的值:

>>> def py_cmp_func(a, b):
...     print("py_cmp_func", a[0], b[0])
...     return 0
...
>>> cmp_func = CMPFUNC(py_cmp_func)
>>>

结果:

>>> qsort(ia, len(ia), sizeof(c_int), cmp_func)  
py_cmp_func 5 1
py_cmp_func 33 99
py_cmp_func 7 33
py_cmp_func 5 7
py_cmp_func 1 7
>>>

现在我们可以实际比较这两个项目并返回一个有用的结果:

>>> def py_cmp_func(a, b):
...     print("py_cmp_func", a[0], b[0])
...     return a[0] - b[0]
...
>>>
>>> qsort(ia, len(ia), sizeof(c_int), CMPFUNC(py_cmp_func)) 
py_cmp_func 5 1
py_cmp_func 33 99
py_cmp_func 7 33
py_cmp_func 1 7
py_cmp_func 5 7
>>>

正如我们可以轻松检查的那样,我们的数组现在已排序:

>>> for i in ia: print(i, end=" ")
...
1 5 7 33 99
>>>

函数工厂可以用作装饰器工厂,所以我们不妨这样写:

>>> @CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
... def py_cmp_func(a, b):
...     print("py_cmp_func", a[0], b[0])
...     return a[0] - b[0]
...
>>> qsort(ia, len(ia), sizeof(c_int), py_cmp_func)
py_cmp_func 5 1
py_cmp_func 33 99
py_cmp_func 7 33
py_cmp_func 1 7
py_cmp_func 5 7
>>>

笔记

确保保留对 CFUNCTYPE() 对象的引用,只要它们从 C 代码中使用即可。 ctypes 没有,如果你不这样做,它们可能会被垃圾收集,在进行回调时使你的程序崩溃。

另外,请注意,如果在 Python 控制之外创建的线程中调用回调函数(例如 通过调用回调的外部代码),ctypes 在每次调用时创建一个新的虚拟 Python 线程。 这种行为在大多数情况下是正确的,但这意味着使用 threading.local 存储的值将 not 在不同的回调中存活,即使这些调用来自同一个 C 线程。


访问从 dll 导出的值

一些共享库不仅导出函数,还导出变量。 Python 库本身中的一个示例是 Py_OptimizeFlag,一个整数设置为 0、1 或 2,具体取决于给定的 -O-OO 标志在启动时。

ctypes 可以使用该类型的 in_dll() 类方法访问这样的值。 pythonapi 是一个预定义的符号,可以访问 Python C api:

>>> opt_flag = c_int.in_dll(pythonapi, "Py_OptimizeFlag")
>>> print(opt_flag)
c_long(0)
>>>

如果解释器以 -O 开始,则样本将打印 c_long(1),或 c_long(2) 如果已指定 -OO

一个扩展示例也演示了如何使用指针访问 Python 导出的 PyImport_FrozenModules 指针。

引用该值的文档:

这个指针被初始化为指向一个 struct _frozen 记录数组,由一个成员都是 NULL 或零的记录终止。 导入冻结模块时,将在此表中搜索。 第三方代码可以利用此技巧来提供动态创建的冻结模块集合。


所以操纵这个指针甚至可以证明是有用的。 为了限制示例大小,我们仅展示如何使用 ctypes 读取此表:

>>> from ctypes import *
>>>
>>> class struct_frozen(Structure):
...     _fields_ = [("name", c_char_p),
...                 ("code", POINTER(c_ubyte)),
...                 ("size", c_int)]
...
>>>

我们已经定义了 struct _frozen 数据类型,所以我们可以得到指向表的指针:

>>> FrozenTable = POINTER(struct_frozen)
>>> table = FrozenTable.in_dll(pythonapi, "PyImport_FrozenModules")
>>>

由于 tablestruct_frozen 记录数组的 pointer,我们可以迭代它,但我们只需要确保我们的循环终止,因为指针没有大小. 迟早它可能会因访问冲突或其他原因而崩溃,因此最好在我们点击 NULL 条目时跳出循环:

>>> for item in table:
...     if item.name is None:
...         break
...     print(item.name.decode("ascii"), item.size)
...
_frozen_importlib 31764
_frozen_importlib_external 41499
__hello__ 161
__phello__ -161
__phello__.spam 161
>>>

标准 Python 有一个冻结模块和一个冻结包(由负的 size 成员表示)这一事实并不为人所知,它仅用于测试。 例如,尝试使用 import __hello__


惊喜

ctypes 中有一些边缘,你可能会期待一些与实际发生的情况不同的东西。

考虑以下示例:

>>> from ctypes import *
>>> class POINT(Structure):
...     _fields_ = ("x", c_int), ("y", c_int)
...
>>> class RECT(Structure):
...     _fields_ = ("a", POINT), ("b", POINT)
...
>>> p1 = POINT(1, 2)
>>> p2 = POINT(3, 4)
>>> rc = RECT(p1, p2)
>>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)
1 2 3 4
>>> # now swap the two points
>>> rc.a, rc.b = rc.b, rc.a
>>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)
3 4 3 4
>>>

嗯。 我们当然希望最后一条语句打印 3 4 1 2。 发生了什么? 以下是上面 rc.a, rc.b = rc.b, rc.a 行的步骤:

>>> temp0, temp1 = rc.b, rc.a
>>> rc.a = temp0
>>> rc.b = temp1
>>>

请注意,temp0temp1 是仍在使用上述 rc 对象的内部缓冲区的对象。 因此,执行 rc.a = temp0 会将 temp0 的缓冲区内容复制到 rc 的缓冲区中。 这反过来又会改变 temp1 的内容。 所以,最后一个赋值 rc.b = temp1 没有达到预期的效果。

请记住,从结构、联合和数组中检索子对象不会 复制 子对象,而是检索访问根对象的底层缓冲区的包装器对象。

另一个可能与人们期望的行为不同的示例是:

>>> s = c_char_p()
>>> s.value = b"abc def ghi"
>>> s.value
b'abc def ghi'
>>> s.value is s.value
False
>>>

笔记

c_char_p 实例化的对象只能将其值设置为字节或整数。


为什么打印 False? ctypes 实例是包含内存块和一些 描述符 访问内存内容的对象。 在内存块中存储 Python 对象并不存储对象本身,而是存储对象的 contents。 再次访问内容每次都会构造一个新的 Python 对象!


可变大小的数据类型

ctypes 为可变大小的数组和结构提供了一些支持。

resize() 函数可用于调整现有 ctypes 对象的内存缓冲区大小。 该函数将对象作为第一个参数,将请求的字节大小作为第二个参数。 内存块不能小于对象类型指定的自然内存块,如果尝试这样做,则会引发 ValueError

>>> short_array = (c_short * 4)()
>>> print(sizeof(short_array))
8
>>> resize(short_array, 4)
Traceback (most recent call last):
    ...
ValueError: minimum size is 8
>>> resize(short_array, 32)
>>> sizeof(short_array)
32
>>> sizeof(type(short_array))
8
>>>

这很好也很好,但是如何访问包含在这个数组中的附加元素呢? 由于该类型仍然只知道 4 个元素,因此访问其他元素时会出错:

>>> short_array[:]
[0, 0, 0, 0]
>>> short_array[7]
Traceback (most recent call last):
    ...
IndexError: invalid index
>>>

将可变大小数据类型与 ctypes 一起使用的另一种方法是使用 Python 的动态特性,并在已知所需大小后(重新)定义数据类型,具体情况具体分析。


ctypes 参考

查找共享库

使用编译语言编程时,在编译/链接程序以及运行程序时访问共享库。

find_library() 函数的目的是以类似于编译器或运行时加载器所做的方式(在具有多个共享库版本的平台上应加载最新版本)的方式定位库,而 ctypes 库加载器就像程序运行时一样,直接调用运行时加载器。

ctypes.util 模块提供了一个函数,可以帮助确定要加载的库。

ctypes.util.find_library(name)
尝试查找库并返回路径名。 name 是没有任何前缀的库名,如 lib,后缀如 .so, .dylib 或版本号(这是用于 posix 的形式链接器选项 -l)。 如果找不到库,则返回 None

确切的功能取决于系统。

在 Linux 上,find_library() 尝试运行外部程序(/sbin/ldconfiggccobjdumpld)来查找库文件。 它返回库文件的文件名。

3.6 版本变更: 在 Linux 上,如果通过任何其他方式无法找到库,则在搜索库时使用环境变量 LD_LIBRARY_PATH 的值。


这里有些例子:

>>> from ctypes.util import find_library
>>> find_library("m")
'libm.so.6'
>>> find_library("c")
'libc.so.6'
>>> find_library("bz2")
'libbz2.so.1.0'
>>>

在 macOS 上,find_library() 尝试多个预定义的命名方案和路径来定位库,如果成功则返回完整路径名:

>>> from ctypes.util import find_library
>>> find_library("c")
'/usr/lib/libc.dylib'
>>> find_library("m")
'/usr/lib/libm.dylib'
>>> find_library("bz2")
'/usr/lib/libbz2.dylib'
>>> find_library("AGL")
'/System/Library/Frameworks/AGL.framework/AGL'
>>>

在 Windows 上,find_library() 沿着系统搜索路径搜索,并返回完整路径名,但由于没有预定义的命名方案,像 find_library("c") 这样的调用将失败并返回 None

如果使用 ctypes 包装共享库,可能 更好地在开发时确定共享库名称,并将其硬编码到包装器模块中而不是使用 find_library()在运行时定位库。


加载共享库

有几种方法可以将共享库加载到 Python 进程中。 一种方法是实例化以下类之一:

class ctypes.CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0)

此类的实例表示加载的共享库。 这些库中的函数使用标准 C 调用约定,并假定返回 int

在 Windows 上,即使 DLL 名称存在,创建 CDLL 实例也可能会失败。 当未找到加载的 DLL 的依赖 DLL 时,会引发 OSError 错误,并显示消息 “[WinError 126] 找不到指定的模块”。 此错误消息不会不包含丢失的 DLL 的名称,因为 Windows API 不返回此信息,使此错误难以诊断。 要解决此错误并确定未找到哪个 DLL,您需要查找相关 DLL 列表并使用 Windows 调试和跟踪工具确定未找到哪个 DLL。

也可以看看

Microsoft DUMPBIN 工具 - 查找 DLL 依赖项的工具。


class ctypes.OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0)

仅限 Windows:此类的实例表示加载的共享库,这些库中的函数使用 stdcall 调用约定,并假定返回特定于 Windows 的 HRESULT 代码。 HRESULT 值包含指定函数调用是失败还是成功的信息,以及其他错误代码。 如果返回值表示失败,则会自动引发 OSError

3.3 版更改: WindowsError 曾经被提出。

class ctypes.WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=0)

仅限 Windows:此类的实例表示加载的共享库,这些库中的函数使用 stdcall 调用约定,并假定默认返回 int

在 Windows CE 上仅使用标准调用约定,为方便起见,WinDLLOleDLL 使用此平台上的标准调用约定。

Python 全局解释器锁在调用这些库导出的任何函数之前释放,之后重新获取。

class ctypes.PyDLL(name, mode=DEFAULT_MODE, handle=None)

此类的实例的行为类似于 CDLL 实例,除了 Python GIL 在函数调用期间是 不是 释放的,并且在函数执行后检查 Python 错误标志。 如果设置了错误标志,则会引发 Python 异常。

因此,这仅对直接调用 Python C api 函数有用。

所有这些类都可以通过使用至少一个参数(共享库的路径名)调用它们来实例化。 如果你有一个已经加载的共享库的现有句柄,它可以作为 handle 命名参数传递,否则底层平台 dlopenLoadLibrary 函数用于加载库进入进程,并得到它的句柄。

mode 参数可用于指定库的加载方式。 有关详细信息,请参阅 dlopen(3) 联机帮助页。 在 Windows 上,mode 被忽略。 在 posix 系统上,始终添加 RTLD_NOW,并且不可配置。

use_errno 参数设置为 true 时,启用 ctypes 机制,允许以安全的方式访问系统 errno 错误号。 ctypes 维护系统 errno 变量的线程本地副本; 如果您调用使用 use_errno=True 创建的外部函数,那么在函数调用与 ctypes 私有副本交换之前的 errno 值,函数调用后会立即发生同样的情况。

函数 ctypes.get_errno() 返回 ctypes 私有副本的值,函数 ctypes.set_errno() 将 ctypes 私有副本更改为新值并返回之前的值.

use_last_error 参数设置为 true 时,为由 GetLastError()SetLastError() Windows API 函数管理的 Windows 错误代码启用相同的机制; ctypes.get_last_error()ctypes.set_last_error() 用于请求和更改 windows 错误代码的 ctypes 私有副本。

winmode 参数在 Windows 上用于指定库的加载方式(因为 mode 被忽略)。 它采用对 Win32 API LoadLibraryEx 标志参数有效的任何值。 省略时,默认使用导致最安全的 DLL 加载的标志来避免诸如 DLL 劫持之类的问题。 将完整路径传递给 DLL 是确保加载正确的库和依赖项的最安全方法。

3.8 版更改: 添加 winmode 参数。


ctypes.RTLD_GLOBAL
用作 mode 参数的标志。 在此标志不可用的平台上,它被定义为整数零。
ctypes.RTLD_LOCAL
用作 mode 参数的标志。 在不可用的平台上,它与 RTLD_GLOBAL 相同。
ctypes.DEFAULT_MODE
用于加载共享库的默认模式。 在 OSX 10.3 上,这是 RTLD_GLOBAL,否则与 RTLD_LOCAL 相同。

这些类的实例没有公共方法。 共享库导出的函数可以作为属性或索引进行访问。 请注意,通过属性访问函数会缓存结果,因此每次重复访问它都会返回相同的对象。 另一方面,通过索引访问它每次都会返回一个新对象:

>>> from ctypes import CDLL
>>> libc = CDLL("libc.so.6")  # On Linux
>>> libc.time == libc.time
True
>>> libc['time'] == libc['time']
False

以下公共属性可用,它们的名称以下划线开头,以免与导出的函数名称冲突:

PyDLL._handle
用于访问库的系统句柄。
PyDLL._name
在构造函数中传递的库的名称。

共享库也可以通过使用预制对象之一加载,这些对象是 LibraryLoader 类的实例,通过调用 LoadLibrary() 方法,或通过检索库作为加载器的属性实例。

class ctypes.LibraryLoader(dlltype)

加载共享库的类。 dlltype 应该是 CDLLPyDLLWinDLLOleDLL 类型之一。

__getattr__() 具有特殊的行为:它允许通过访问共享库作为库加载器实例的属性来加载它。 结果被缓存,因此重复的属性访问每次都返回相同的库。

LoadLibrary(name)

将共享库加载到进程中并返回。 此方法始终返回库的新实例。

这些预制库加载器可用:

ctypes.cdll
创建 CDLL 实例。
ctypes.windll
仅限 Windows:创建 WinDLL 实例。
ctypes.oledll
仅限 Windows:创建 OleDLL 实例。
ctypes.pydll
创建 PyDLL 实例。

为了直接访问 C Python api,可以使用现成的 Python 共享库对象:

ctypes.pythonapi
PyDLL 的一个实例,将 Python C API 函数公开为属性。 请注意,所有这些函数都假定返回 C int,这当然并不总是正确的,因此您必须分配正确的 restype 属性才能使用这些函数。


外部函数

如上一节所述,外部函数可以作为加载的共享库的属性进行访问。 以这种方式创建的函数对象默认接受任意数量的参数,接受任何 ctypes 数据实例作为参数,并返回库加载器指定的默认结果类型。 它们是私有类的实例:

class ctypes._FuncPtr

C 可调用外部函数的基类。

外部函数的实例也是 C 兼容的数据类型; 它们代表 C 函数指针。

这种行为可以通过分配给外部函数对象的特殊属性来定制。

restype

分配一个 ctypes 类型来指定外部函数的结果类型。 将 None 用于 void,该函数不返回任何内容。

可以分配一个不是 ctypes 类型的可调用 Python 对象,在这种情况下,假定函数返回 C int,并且将使用此整数调用可调用对象,允许进一步处理或错误检查。 不推荐使用它,为了更灵活的后处理或错误检查,请使用 ctypes 数据类型作为 restype 并将可调用对象分配给 errcheck 属性。

argtypes

分配一个 ctypes 类型的元组来指定函数接受的参数类型。 使用 stdcall 调用约定的函数只能使用与此元组长度相同数量的参数来调用; 使用 C 调用约定的函数也接受额外的、未指定的参数。

当调用外部函数时,每个实参都传递给 argtypes 元组中项的 from_param() 类方法,该方法允许将实参适配到外部函数接受。 例如, argtypes 元组中的 c_char_p 项将使用 ctypes 转换规则将作为参数传递的字符串转换为字节对象。

新:现在可以将项目放入不是 ctypes 类型的 argtypes 中,但每个项目必须有一个 from_param() 方法,该方法返回一个可用作参数的值(整数、字符串、ctypes 实例)。 这允许定义可以适应自定义对象作为函数参数的适配器。

errcheck

为该属性分配一个 Python 函数或另一个可调用函数。 将使用三个或更多参数调用可调用对象:

callable(result, func, arguments)

result 是外部函数返回的内容,由 restype 属性指定。

func 是外部函数对象本身,这允许重用相同的可调用对象来检查或后处理多个函数的结果。

arguments 是一个包含最初传递给函数调用的参数的元组,这允许对所用参数的行为进行专门化。

此函数返回的对象将从外部函数调用返回,但如果外部函数调用失败,它也可以检查结果值并引发异常。

exception ctypes.ArgumentError
当外部函数调用无法转换传递的参数之一时,会引发此异常。


函数原型

也可以通过实例化函数原型来创建外部函数。 函数原型类似于 C 中的函数原型; 它们描述了一个函数(返回类型、参数类型、调用约定)而不定义实现。 工厂函数必须使用所需的结果类型和函数的参数类型来调用,并且可以用作装饰器工厂,因此可以通过 @wrapper 语法应用于函数。 有关示例,请参阅 回调函数

ctypes.CFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)
返回的函数原型创建使用标准 C 调用约定的函数。 该函数将在调用期间释放 GIL。 如果use_errno设置为true,系统errno变量的ctypes私有副本在调用前后与真实的errno值交换; use_last_error 对 Windows 错误代码执行相同操作。
ctypes.WINFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)
仅限 Windows:返回的函数原型创建使用 stdcall 调用约定的函数,但在 Windows CE 上除外,其中 WINFUNCTYPE()CFUNCTYPE() 相同。 该函数将在调用期间释放 GIL。 use_errnouse_last_error 含义同上。
ctypes.PYFUNCTYPE(restype, *argtypes)
返回的函数原型创建使用 Python 调用约定的函数。 该函数将 在调用过程中释放 GIL。

这些工厂函数创建的函数原型可以通过不同的方式实例化,具体取决于调用中参数的类型和数量:

prototype(address)
返回指定地址处的外部函数,该函数必须是整数。
prototype(callable)
从 Python callable 创建 C 可调用函数(回调函数)。
prototype(func_spec[, paramflags])
返回共享库导出的外部函数。 func_spec 必须是一个二元组 (name_or_ordinal, library)。 第一项是作为字符串的导出函数的名称,或者作为小整数的导出函数的序数。 第二项是共享库实例。
prototype(vtbl_index, name[, paramflags[, iid]])

返回将调用 COM 方法的外部函数。 vtbl_index是虚函数表的索引,一个小的非负整数。 name 是 COM 方法的名称。 iid 是一个可选的指向接口标识符的指针,用于扩展错误报告。

COM 方法使用特殊的调用约定:除了 argtypes 元组中指定的那些参数之外,它们还需要一个指向 COM 接口的指针作为第一个参数。

可选的 paramflags 参数创建具有比上述功能更多功能的外部函数包装器。

paramflags 必须是与 argtypes 长度相同的元组。

此元组中的每一项都包含有关参数的更多信息,它必须是包含一项、两项或三项的元组。

第一项是一个整数,包含参数的方向标志组合:

1
指定函数的输入参数。
2
输出参数。 外部函数填充一个值。
4
默认为整数零的输入参数。


可选的第二项是字符串形式的参数名称。 如果指定了此项,则可以使用命名参数调用外部函数。

可选的第三项是该参数的默认值。


此示例演示如何包装 Windows MessageBoxW 函数,以便它支持默认参数和命名参数。 windows 头文件中的 C 声明是这样的:

WINUSERAPI int WINAPI
MessageBoxW(
    HWND hWnd,
    LPCWSTR lpText,
    LPCWSTR lpCaption,
    UINT uType);

这是 ctypes 的包装:

>>> from ctypes import c_int, WINFUNCTYPE, windll
>>> from ctypes.wintypes import HWND, LPCWSTR, UINT
>>> prototype = WINFUNCTYPE(c_int, HWND, LPCWSTR, LPCWSTR, UINT)
>>> paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1, "caption", "Hello from ctypes"), (1, "flags", 0)
>>> MessageBox = prototype(("MessageBoxW", windll.user32), paramflags)

MessageBox 外部函数现在可以通过以下方式调用:

>>> MessageBox()
>>> MessageBox(text="Spam, spam, spam")
>>> MessageBox(flags=2, text="foo bar")

第二个示例演示输出参数。 win32 GetWindowRect 函数通过将它们复制到调用者必须提供的 RECT 结构中来检索指定窗口的尺寸。 这是 C 声明:

WINUSERAPI BOOL WINAPI
GetWindowRect(
     HWND hWnd,
     LPRECT lpRect);

这是 ctypes 的包装:

>>> from ctypes import POINTER, WINFUNCTYPE, windll, WinError
>>> from ctypes.wintypes import BOOL, HWND, RECT
>>> prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT))
>>> paramflags = (1, "hwnd"), (2, "lprect")
>>> GetWindowRect = prototype(("GetWindowRect", windll.user32), paramflags)
>>>

如果有一个输出参数值,带有输出参数的函数将自动返回输出参数值,或者当有多个输出参数值时返回一个包含输出参数值的元组,因此 GetWindowRect 函数现在在调用时返回一个 RECT 实例。

输出参数可以结合errcheck协议进行进一步的输出处理和错误检查。 win32 GetWindowRect api 函数返回一个 BOOL 来表示成功或失败,因此该函数可以进行错误检查,并在 api 调用失败时引发异常:

>>> def errcheck(result, func, args):
...     if not result:
...         raise WinError()
...     return args
...
>>> GetWindowRect.errcheck = errcheck
>>>

如果 errcheck 函数返回它接收到的参数元组不变,ctypes 继续它对输出参数所做的正常处理。 如果你想返回一个窗口坐标元组而不是一个 RECT 实例,你可以检索函数中的字段并返回它们,正常处理将不再发生:

>>> def errcheck(result, func, args):
...     if not result:
...         raise WinError()
...     rc = args[1]
...     return rc.left, rc.top, rc.bottom, rc.right
...
>>> GetWindowRect.errcheck = errcheck
>>>

实用功能

ctypes.addressof(obj)
以整数形式返回内存缓冲区的地址。 obj 必须是 ctypes 类型的实例。
ctypes.alignment(obj_or_type)
返回 ctypes 类型的对齐要求。 obj_or_type 必须是 ctypes 类型或实例。
ctypes.byref(obj[, offset])

返回一个指向 obj 的轻量级指针,它必须是一个 ctypes 类型的实例。 offset 默认为零,并且必须是将添加到内部指针值的整数。

byref(obj, offset) 对应这个 C 代码:

(((char *)&obj) + offset)

返回的对象只能用作外部函数调用参数。 它的行为类似于 pointer(obj),但构建速度要快得多。

ctypes.cast(obj, type)
此函数类似于 C 中的强制转换运算符。 它返回一个 type 的新实例,它指向与 obj 相同的内存块。 type 必须是指针类型,obj 必须是可以解释为指针的对象。
ctypes.create_string_buffer(init_or_size, size=None)

此函数创建一个可变字符缓冲区。 返回的对象是 c_char 的 ctypes 数组。

init_or_size 必须是指定数组大小的整数,或用于初始化数组项的字节对象。

如果将字节对象指定为第一个参数,则缓冲区将比其长度大一个项目,以便数组中的最后一个元素是 NUL 终止字符。 一个整数可以作为第二个参数传递,如果不应该使用字节的长度,它允许指定数组的大小。

ctypes.create_unicode_buffer(init_or_size, size=None)

此函数创建一个可变的 unicode 字符缓冲区。 返回的对象是 c_wchar 的 ctypes 数组。

init_or_size 必须是指定数组大小的整数,或用于初始化数组项的字符串。

如果将字符串指定为第一个参数,则缓冲区将比字符串的长度大一个项目,以便数组中的最后一个元素是 NUL 终止字符。 一个整数可以作为第二个参数传递,如果不应该使用字符串的长度,它允许指定数组的大小。

ctypes.DllCanUnloadNow()
仅适用于 Windows:此函数是一个钩子,它允许使用 ctypes 实现进程内 COM 服务器。 它是从 _ctypes 扩展 dll 导出的 DllCanUnloadNow 函数调用的。
ctypes.DllGetClassObject()
仅适用于 Windows:此函数是一个钩子,它允许使用 ctypes 实现进程内 COM 服务器。 它是从 _ctypes 扩展 dll 导出的 DllGetClassObject 函数调用的。
ctypes.util.find_library(name)

尝试查找库并返回路径名。 name 是没有任何前缀的库名,如 lib,后缀如 .so, .dylib 或版本号(这是用于 posix 链接器的形式选项 -l)。 如果找不到库,则返回 None

确切的功能取决于系统。

ctypes.util.find_msvcrt()

仅限 Windows:返回 Python 和扩展模块使用的 VC 运行时库的文件名。 如果无法确定库的名称,则返回 None

如果您需要释放内存,例如,由调用 free(void *) 的扩展模块分配,那么使用分配内存的同一库中的函数很重要。

ctypes.FormatError([code])
仅限 Windows:返回错误代码 code 的文本描述。 如果未指定错误代码,则通过调用 Windows api 函数 GetLastError 使用最后一个错误代码。
ctypes.GetLastError()
仅限 Windows:返回 Windows 在调用线程中设置的最后一个错误代码。 此函数直接调用Windows GetLastError() 函数,它不返回错误代码的ctypes-private 副本。
ctypes.get_errno()
返回调用线程中系统 errno 变量的 ctypes-private 副本的当前值。
ctypes.get_last_error()
仅限 Windows:返回调用线程中系统 LastError 变量的 ctypes-private 副本的当前值。
ctypes.memmove(dst, src, count)
与标准 C memmove 库函数相同:将 count 个字节从 src 复制到 dstdstsrc 必须是可以转换为指针的整数或 ctypes 实例。
ctypes.memset(dst, c, count)
与标准 C memset 库函数相同:用 count 个字节的值 c 填充地址 dst 处的内存块。 dst 必须是指定地址或 ctypes 实例的整数。
ctypes.POINTER(type)
这个工厂函数创建并返回一个新的 ctypes 指针类型。 指针类型在内部被缓存和重用,所以重复调用这个函数很便宜。 type 必须是 ctypes 类型。
ctypes.pointer(obj)

此函数创建一个新的指针实例,指向 obj。 返回的对象的类型为 POINTER(type(obj))

注意:如果您只想将指向对象的指针传递给外部函数调用,您应该使用 byref(obj),它要快得多。

ctypes.resize(obj, size)
此函数调整 obj 的内部内存缓冲区大小,它必须是 ctypes 类型的实例。 不可能使缓冲区小于对象类型的原始大小,如 sizeof(type(obj)) 给出的,但可以扩大缓冲区。
ctypes.set_errno(value)
将调用线程中系统 errno 变量的 ctypes-private 副本的当前值设置为 value 并返回之前的值。
ctypes.set_last_error(value)
仅限 Windows:将调用线程中系统 LastError 变量的 ctypes-private 副本的当前值设置为 value 并返回先前的值。
ctypes.sizeof(obj_or_type)
返回 ctypes 类型或实例内存缓冲区的大小(以字节为单位)。 与 C sizeof 运算符相同。
ctypes.string_at(address, size=- 1)
此函数返回从内存地址 address 开始的 C 字符串作为字节对象。 如果指定了大小,则将其用作大小,否则假定字符串以零结尾。
ctypes.WinError(code=None, descr=None)

仅限 Windows:这个函数可能是 ctypes 中命名最差的东西。 它创建了一个 OSError 实例。 如果未指定 code,则调用 GetLastError 以确定错误代码。 如果未指定 descr,则调用 FormatError() 以获取错误的文本描述。

3.3 版更改: 曾经创建 WindowsError 的实例。

ctypes.wstring_at(address, size=- 1)
此函数以字符串形式返回从内存地址 address 开始的宽字符串。 如果指定了 size,则将其用作字符串的字符数,否则假定字符串以零结尾。


数据类型

class ctypes._CData

这个非公共类是所有 ctypes 数据类型的公共基类。 除其他外,所有 ctypes 类型实例都包含一个存储 C 兼容数据的内存块; 内存块的地址由 addressof() 辅助函数返回。 另一个实例变量公开为 _objects; 这包含其他需要保持活动状态的 Python 对象,以防内存块包含指针。

ctypes数据类型的常用方法,这些都是类方法(准确的说是元类的方法):

from_buffer(source[, offset])

此方法返回一个 ctypes 实例,该实例共享 source 对象的缓冲区。 source 对象必须支持可写缓冲区接口。 可选的 offset 参数以字节为单位指定源缓冲区的偏移量; 默认为零。 如果源缓冲区不够大,则会引发 ValueError

from_buffer_copy(source[, offset])

此方法创建一个 ctypes 实例,从必须可读的 source 对象缓冲区复制缓冲区。 可选的 offset 参数以字节为单位指定源缓冲区的偏移量; 默认为零。 如果源缓冲区不够大,则会引发 ValueError

from_address(address)

此方法使用 address 指定的内存返回一个 ctypes 类型实例,该内存必须是整数。

from_param(obj)

此方法使 obj 适应 ctypes 类型。 当类型存在于外部函数的 argtypes 元组中时,使用外部函数调用中使用的实际对象调用它; 它必须返回一个可以用作函数调用参数的对象。

所有 ctypes 数据类型都有此类方法的默认实现,如果它是该类型的实例,则通常返回 obj。 有些类型也接受其他对象。

in_dll(library, name)

此方法返回共享库导出的 ctypes 类型实例。 name为导出数据的符号名,library为加载的共享库。

ctypes 数据类型的常见实例变量:

_b_base_

有时 ctypes 数据实例不拥有它们包含的内存块,而是共享基础对象的部分内存块。 _b_base_ 只读成员是拥有内存块的根 ctypes 对象。

_b_needsfree_

当 ctypes 数据实例本身分配了内存块时,这个只读变量为真,否则为假。

_objects

该成员是 None 或包含需要保持活动状态的 Python 对象的字典,以便内存块内容保持有效。 此对象仅用于调试; 永远不要修改这本词典的内容。


基本数据类型

class ctypes._SimpleCData

这个非公共类是所有基本 ctypes 数据类型的基类。 在这里提到它是因为它包含基本 ctypes 数据类型的公共属性。 _SimpleCData_CData 的子类,所以继承了它们的方法和属性。 现在可以腌制不包含也不包含指针的 ctypes 数据类型。

实例有一个属性:

value

该属性包含实例的实际值。 对于整数和指针类型,它是一个整数,对于字符类型,它是一个单字符字节对象或字符串,对于字符指针类型,它是一个 Python 字节对象或字符串。

当从 ctypes 实例中检索 value 属性时,通常每次都会返回一个新对象。 ctypes 实现原对象返回,总是构造一个新对象。 对于所有其他 ctypes 对象实例也是如此。

基本数据类型在作为外部函数调用结果返回时,或者例如通过检索结构字段成员或数组项时,会透明地转换为本地 Python 类型。 换句话说,如果一个外部函数有一个 c_char_prestype,你将总是收到一个 Python 字节对象,而不是 一个 c_char_p 实例.

基本数据类型的子类 不会 继承此行为。 因此,如果外部函数 restypec_void_p 的子类,您将从函数调用中收到该子类的实例。 当然,您可以通过访问 value 属性来获取指针的值。

这些是基本的 ctypes 数据类型:

class ctypes.c_byte
表示 C signed char 数据类型,并将值解释为小整数。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
class ctypes.c_char
表示 C char 数据类型,并将值解释为单个字符。 构造函数接受一个可选的字符串初始化器,字符串的长度必须正好是一个字符。
class ctypes.c_char_p
当它指向以零结尾的字符串时,表示 C char* 数据类型。 对于也可能指向二进制数据的通用字符指针,必须使用 POINTER(c_char)。 构造函数接受一个整数地址或一个字节对象。
class ctypes.c_double
表示 C double 数据类型。 构造函数接受一个可选的浮点初始化器。
class ctypes.c_longdouble
表示 C long double 数据类型。 构造函数接受一个可选的浮点初始化器。 在 sizeof(long double) == sizeof(double) 它是 c_double 的别名的平台上。
class ctypes.c_float
表示 C float 数据类型。 构造函数接受一个可选的浮点初始化器。
class ctypes.c_int
表示 C signed int 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。 在 sizeof(int) == sizeof(long) 它是 c_long 的别名的平台上。
class ctypes.c_int8
表示 C 8 位 signed int 数据类型。 通常是 c_byte 的别名。
class ctypes.c_int16
表示 C 16 位 signed int 数据类型。 通常是 c_short 的别名。
class ctypes.c_int32
表示 C 32 位 signed int 数据类型。 通常是 c_int 的别名。
class ctypes.c_int64
表示 C 64 位 signed int 数据类型。 通常是 c_longlong 的别名。
class ctypes.c_long
表示 C signed long 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
class ctypes.c_longlong
表示 C signed long long 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
class ctypes.c_short
表示 C signed short 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
class ctypes.c_size_t
表示 C size_t 数据类型。
class ctypes.c_ssize_t

表示 C ssize_t 数据类型。

3.2 版中的新功能。

class ctypes.c_ubyte
表示 C unsigned char 数据类型,它将值解释为小整数。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
class ctypes.c_uint
表示 C unsigned int 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。 在 sizeof(int) == sizeof(long) 它是 c_ulong 的别名的平台上。
class ctypes.c_uint8
表示 C 8 位 unsigned int 数据类型。 通常是 c_ubyte 的别名。
class ctypes.c_uint16
表示 C 16 位 unsigned int 数据类型。 通常是 c_ushort 的别名。
class ctypes.c_uint32
表示 C 32 位 unsigned int 数据类型。 通常是 c_uint 的别名。
class ctypes.c_uint64
表示 C 64 位 unsigned int 数据类型。 通常是 c_ulonglong 的别名。
class ctypes.c_ulong
表示 C unsigned long 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
class ctypes.c_ulonglong
表示 C unsigned long long 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
class ctypes.c_ushort
表示 C unsigned short 数据类型。 构造函数接受一个可选的整数初始化器; 没有进行溢出检查。
class ctypes.c_void_p
表示 C void* 类型。 该值表示为整数。 构造函数接受一个可选的整数初始值设定项。
class ctypes.c_wchar
表示 C wchar_t 数据类型,并将值解释为单字符 unicode 字符串。 构造函数接受一个可选的字符串初始化器,字符串的长度必须正好是一个字符。
class ctypes.c_wchar_p
表示 C wchar_t* 数据类型,它必须是指向以零结尾的宽字符串的指针。 构造函数接受一个整数地址或字符串。
class ctypes.c_bool
表示 C bool 数据类型(更准确地说,是 C99 中的 _Bool)。 它的值可以是 TrueFalse,构造函数接受任何具有真值的对象。
class ctypes.HRESULT
仅限 Windows:表示 HRESULT 值,其中包含函数或方法调用的成功或错误信息。
class ctypes.py_object
表示 C PyObject* 数据类型。 不带参数调用它会创建一个 NULL PyObject* 指针。

ctypes.wintypes 模块提供了相当多的其他 Windows 特定数据类型,例如 HWNDWPARAMDWORD。 还定义了一些有用的结构,如 MSGRECT


结构化数据类型

class ctypes.Union(*args, **kw)
本机字节顺序的联合的抽象基类。
class ctypes.BigEndianStructure(*args, **kw)
big endian 字节顺序结构的抽象基类。
class ctypes.LittleEndianStructure(*args, **kw)
little endian 字节顺序结构的抽象基类。

具有非本地字节顺序的结构不能包含指针类型字段,或包含指针类型字段的任何其他数据类型。

class ctypes.Structure(*args, **kw)

native 字节顺序结构的抽象基类。

具体的结构和联合类型必须通过继承这些类型之一来创建,并且至少定义一个 _fields_ 类变量。 ctypes 将创建 描述符 ,允许通过直接属性访问读取和写入字段。 这些是

_fields_

定义结构字段的序列。 项必须是 2 元组或 3 元组。 第一项是字段名称,第二项指定字段类型; 它可以是任何 ctypes 数据类型。

对于像 c_int 这样的整数类型字段,可以给出第三个可选项。 它必须是一个小的正整数,用于定义字段的位宽。

字段名称在一个结构或联合中必须是唯一的。 未选中此项,当名称重复时,只能访问一个字段。

可以在定义 Structure 子类的 class 语句之后定义 _fields_ 类变量 ,这允许创建直接或间接引用自身的数据类型:

class List(Structure):
    pass
List._fields_ = [("pnext", POINTER(List)),
                 ...
                ]

然而,_fields_ 类变量必须在第一次使用类型之前定义(创建一个实例,在它上面调用 sizeof(),等等)。 稍后对 _fields_ 类变量的赋值将引发 AttributeError。

可以定义结构类型的子子类,它们继承基类的字段加上子子类中定义的 _fields_(如果有)。

_pack_

一个可选的小整数,允许覆盖实例中结构字段的对齐方式。 _pack_ 必须在分配 _fields_ 时已经定义,否则无效。

_anonymous_

列出未命名(匿名)字段名称的可选序列。 _anonymous_ 必须在分配_fields_ 时已经定义,否则无效。

此变量中列出的字段必须是结构或联合类型字段。 ctypes 将在允许直接访问嵌套字段的结构类型中创建描述符,而无需创建结构或联合字段。

这是一个示例类型(Windows):

class _U(Union):
    _fields_ = [("lptdesc", POINTER(TYPEDESC)),
                ("lpadesc", POINTER(ARRAYDESC)),
                ("hreftype", HREFTYPE)]

class TYPEDESC(Structure):
    _anonymous_ = ("u",)
    _fields_ = [("u", _U),
                ("vt", VARTYPE)]

TYPEDESC 结构描述了一种 COM 数据类型,vt 字段指定哪一个联合字段是有效的。 由于 u 字段被定义为匿名字段,现在可以直接从 TYPEDESC 实例访问成员。 td.lptdesctd.u.lptdesc 是等价的,但前者更快,因为它不需要创建临时联合实例:

td = TYPEDESC()
td.vt = VT_PTR
td.lptdesc = POINTER(some_type)
td.u.lptdesc = POINTER(some_type)

可以定义结构的子子类,它们继承基类的字段。 如果子类定义具有单独的 _fields_ 变量,则在此指定的字段将附加到基类的字段。

结构和联合构造函数接受位置参数和关键字参数。 位置参数用于按照它们出现在 _fields_ 中的相同顺序初始化成员字段。 构造函数中的关键字参数被解释为属性赋值,因此它们将使用相同的名称初始化 _fields_,或者为 _fields_ 中不存在的名称创建新属性。


数组和指针

class ctypes.Array(*args)

数组的抽象基类。

创建具体数组类型的推荐方法是将任何 ctypes 数据类型乘以一个正整数。 或者,您可以子类化此类型并定义 _length__type_ 类变量。 可以使用标准下标和切片访问来读取和写入数组元素; 对于切片读取,结果对象是 不是 本身是 数组

_length_

一个正整数,指定数组中的元素数。 超出范围的下标会导致 IndexError。 将由 len() 返回。

_type_

指定数组中每个元素的类型。

数组子类构造函数接受位置参数,用于按顺序初始化元素。

class ctypes._Pointer

指针的私有抽象基类。

具体的指针类型是通过使用将要指向的类型调用 POINTER() 来创建的; 这是由 pointer() 自动完成的。

如果指针指向数组,则可以使用标准下标和切片访问读取和写入其元素。 指针对象没有大小,因此 len() 将引发 TypeError。 负下标将在 之前从内存中读取 指针(如在 C 中),超出范围的下标可能会因访问冲突而崩溃(如果你很幸运)。

_type_

指定指向的类型。

contents

返回指针指向的对象。 分配给该属性会将指针更改为指向所分配的对象。