# SOME DESCRIPTIVE TITLE. # Copyright (C) 2001-2025, Python Software Foundation # This file is distributed under the same license as the Python package. # FIRST AUTHOR , YEAR. # # Translators: # Rafael Fontenelle , 2025 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: Python 3.12\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-07-25 16:03+0000\n" "PO-Revision-Date: 2025-07-18 19:57+0000\n" "Last-Translator: Rafael Fontenelle , 2025\n" "Language-Team: Chinese (China) (https://app.transifex.com/python-doc/teams/5390/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" #: ../../library/ctypes.rst:2 msgid ":mod:`!ctypes` --- A foreign function library for Python" msgstr ":mod:`!ctypes` --- Python 的外部函数库" #: ../../library/ctypes.rst:9 msgid "**Source code:** :source:`Lib/ctypes`" msgstr "**源代码:** :source:`Lib/ctypes`" #: ../../library/ctypes.rst:13 msgid "" ":mod:`ctypes` 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." msgstr "" ":mod:`ctypes` 是 Python 的外部函数库。它提供了与 C 兼容的数据类型,并允许调用 DLL 或共享库中的函数。可使用该模块以纯 " "Python 形式对这些库进行封装。" #: ../../library/ctypes.rst:21 msgid "ctypes tutorial" msgstr "ctypes 教程" #: ../../library/ctypes.rst:23 msgid "" "Note: The code samples in this tutorial use :mod:`doctest` to make sure that" " they actually work. Since some code samples behave differently under " "Linux, Windows, or macOS, they contain doctest directives in comments." msgstr "" "注:本教程中的示例代码使用 :mod:`doctest` 来保证它们能正确运行。 由于有些代码示例在 Linux, Windows 或 macOS " "上的行为有所不同,它们在注释中包含了一些 doctest 指令。" #: ../../library/ctypes.rst:27 msgid "" "Note: Some code samples reference the ctypes :class:`c_int` type. On " "platforms where ``sizeof(long) == sizeof(int)`` it is an alias to " ":class:`c_long`. So, you should not be confused if :class:`c_long` is " "printed if you would expect :class:`c_int` --- they are actually the same " "type." msgstr "" "注意:部分示例代码引用了 ctypes :class:`c_int` 类型。在 ``sizeof(long) == sizeof(int)`` " "的平台上此类型是 :class:`c_long` 的一个别名。所以,在程序输出 :class:`c_long` 而不是你期望的 " ":class:`c_int` 时不必感到迷惑 --- 它们实际上是同一种类型。" #: ../../library/ctypes.rst:35 msgid "Loading dynamic link libraries" msgstr "载入动态连接库" #: ../../library/ctypes.rst:37 msgid "" ":mod:`ctypes` exports the *cdll*, and on Windows *windll* and *oledll* " "objects, for loading dynamic link libraries." msgstr "" ":mod:`ctypes` 导出了 *cdll* 对象,在 Windows 系统中还导出了 *windll* 和 *oledll* " "对象用于载入动态连接库。" #: ../../library/ctypes.rst:40 msgid "" "You load libraries by accessing them as attributes of these objects. *cdll* " "loads libraries which export functions using the standard ``cdecl`` calling " "convention, while *windll* libraries call functions using the ``stdcall`` " "calling convention. *oledll* also uses the ``stdcall`` calling convention, " "and assumes the functions return a Windows :c:type:`!HRESULT` error code. " "The error code is used to automatically raise an :class:`OSError` exception " "when the function call fails." msgstr "" "您可以通过访问这些对象的属性来加载库。 *cdll* 加载使用标准 ``cdecl`` 调用约定导出函数的库,而 *windll* 库则使用 " "``stdcall`` 调用约定调用函数。 *oledll* 也使用 ``stdcall`` 调用约定,并假定函数返回 Windows " ":c:type:`!HRESULT` 错误代码。 当函数调用失败时会使用错误代码自动引发 :class:`OSError` 异常。" #: ../../library/ctypes.rst:48 msgid "" "Windows errors used to raise :exc:`WindowsError`, which is now an alias of " ":exc:`OSError`." msgstr "原来在 Windows 下抛出的异常类型 :exc:`WindowsError` 现在是 :exc:`OSError` 的一个别名。" #: ../../library/ctypes.rst:53 msgid "" "Here are some examples for Windows. Note that ``msvcrt`` is the MS standard " "C library containing most standard C functions, and uses the ``cdecl`` " "calling convention::" msgstr "" "这是一些 Windows 下的例子。 请注意 ``msvcrt`` 是包含大部分 C 函数的 MS 标准 C 库,并会使用 ``cdecl`` " "调用惯例::" #: ../../library/ctypes.rst:57 msgid "" ">>> from ctypes import *\n" ">>> print(windll.kernel32)\n" "\n" ">>> print(cdll.msvcrt)\n" "\n" ">>> libc = cdll.msvcrt\n" ">>>" msgstr "" ">>> from ctypes import *\n" ">>> print(windll.kernel32)\n" "\n" ">>> print(cdll.msvcrt)\n" "\n" ">>> libc = cdll.msvcrt\n" ">>>" #: ../../library/ctypes.rst:65 msgid "Windows appends the usual ``.dll`` file suffix automatically." msgstr "Windows 会自动添加通常的 ``.dll`` 文件扩展名。" #: ../../library/ctypes.rst:68 msgid "" "Accessing the standard C library through ``cdll.msvcrt`` will use an " "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 ``msvcrt`` module." msgstr "" "通过 ``cdll.msvcrt`` 调用的标准 C 函数,可能会导致调用一个过时的,与当前 Python 所不兼容的函数。因此,请尽量使用标准的 " "Python 函数,而不要使用 ``msvcrt`` 模块。" #: ../../library/ctypes.rst:73 msgid "" "On Linux, it is required to specify the filename *including* the extension " "to load a library, so attribute access can not be used to load libraries. " "Either the :meth:`~LibraryLoader.LoadLibrary` method of the dll loaders " "should be used, or you should load the library by creating an instance of " "CDLL by calling the constructor::" msgstr "" "在 Linux 中,要求指定文件名 *包括* 扩展名来加载库,因此不能使用属性访问的方式来加载库。 你应当使用 dll 加载器的 " ":meth:`~LibraryLoader.LoadLibrary` 方法,或是应当通过调用构造器创建 CDLL 的实例来加载库::" #: ../../library/ctypes.rst:79 msgid "" ">>> cdll.LoadLibrary(\"libc.so.6\")\n" "\n" ">>> libc = CDLL(\"libc.so.6\")\n" ">>> libc\n" "\n" ">>>" msgstr "" ">>> cdll.LoadLibrary(\"libc.so.6\")\n" "\n" ">>> libc = CDLL(\"libc.so.6\")\n" ">>> libc\n" "\n" ">>>" #: ../../library/ctypes.rst:92 msgid "Accessing functions from loaded dlls" msgstr "操作导入的动态链接库中的函数" #: ../../library/ctypes.rst:94 msgid "Functions are accessed as attributes of dll objects::" msgstr "通过操作dll对象的属性来操作这些函数。" #: ../../library/ctypes.rst:96 msgid "" ">>> libc.printf\n" "<_FuncPtr object at 0x...>\n" ">>> print(windll.kernel32.GetModuleHandleA)\n" "<_FuncPtr object at 0x...>\n" ">>> print(windll.kernel32.MyOwnFunction)\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" " File \"ctypes.py\", line 239, in __getattr__\n" " func = _StdcallFuncPtr(name, self)\n" "AttributeError: function 'MyOwnFunction' not found\n" ">>>" msgstr "" ">>> libc.printf\n" "<_FuncPtr object at 0x...>\n" ">>> print(windll.kernel32.GetModuleHandleA)\n" "<_FuncPtr object at 0x...>\n" ">>> print(windll.kernel32.MyOwnFunction)\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" " File \"ctypes.py\", line 239, in __getattr__\n" " func = _StdcallFuncPtr(name, self)\n" "AttributeError: function 'MyOwnFunction' not found\n" ">>>" #: ../../library/ctypes.rst:108 msgid "" "Note that win32 system dlls like ``kernel32`` and ``user32`` often export " "ANSI as well as UNICODE versions of a function. The UNICODE version is " "exported with a ``W`` appended to the name, while the ANSI version is " "exported with an ``A`` appended to the name. The win32 ``GetModuleHandle`` " "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 " "``GetModuleHandle`` depending on whether UNICODE is defined or not::" msgstr "" "请注意 win32 系统的动态库如 ``kernel32`` 和 ``user32`` 通常会同时导出一个函数的 ANSI 版本和 UNICODE " "版本。 UNICODE 版本导出时会在名称后加上 ``W``,而 ANSI 版本导出时会在名称后加上 ``A``。 win32 " "``GetModuleHandle`` 函数会为给定的模块名称返回一个 *模块句柄*,它具有以下的 C 原型,以及一个被用来根据是否定义了 " "UNICODE 将其中之一暴露为 ``GetModuleHandle`` 的宏::" #: ../../library/ctypes.rst:116 msgid "" "/* ANSI version */\n" "HMODULE GetModuleHandleA(LPCSTR lpModuleName);\n" "/* UNICODE version */\n" "HMODULE GetModuleHandleW(LPCWSTR lpModuleName);" msgstr "" "/* ANSI version */\n" "HMODULE GetModuleHandleA(LPCSTR lpModuleName);\n" "/* UNICODE version */\n" "HMODULE GetModuleHandleW(LPCWSTR lpModuleName);" #: ../../library/ctypes.rst:121 msgid "" "*windll* does not try to select one of them by magic, you must access the " "version you need by specifying ``GetModuleHandleA`` or ``GetModuleHandleW`` " "explicitly, and then call it with bytes or string objects respectively." msgstr "" "*windll* 不会通过这样的魔法手段来帮你决定选择哪一种函数,你必须显式的调用 ``GetModuleHandleA`` 或 " "``GetModuleHandleW``,并分别使用字节对象或字符串对象作参数。" #: ../../library/ctypes.rst:125 msgid "" "Sometimes, dlls export functions with names which aren't valid Python " "identifiers, like ``\"??2@YAPAXI@Z\"``. In this case you have to use " ":func:`getattr` to retrieve the function::" msgstr "" "有时候,dlls的导出的函数名不符合 Python 的标识符规范,比如 ``\"??2@YAPAXI@Z\"``。此时,你必须使用 " ":func:`getattr` 方法来获得该函数。" #: ../../library/ctypes.rst:129 msgid "" ">>> getattr(cdll.msvcrt, \"??2@YAPAXI@Z\")\n" "<_FuncPtr object at 0x...>\n" ">>>" msgstr "" ">>> getattr(cdll.msvcrt, \"??2@YAPAXI@Z\")\n" "<_FuncPtr object at 0x...>\n" ">>>" #: ../../library/ctypes.rst:133 msgid "" "On Windows, some dlls export functions not by name but by ordinal. These " "functions can be accessed by indexing the dll object with the ordinal " "number::" msgstr "" "Windows 下,有些 dll 导出的函数没有函数名,而是通过其顺序号调用。对此类函数,你也可以通过 dll 对象的数值索引来操作这些函数。" #: ../../library/ctypes.rst:136 msgid "" ">>> cdll.kernel32[1]\n" "<_FuncPtr object at 0x...>\n" ">>> cdll.kernel32[0]\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" " File \"ctypes.py\", line 310, in __getitem__\n" " func = _StdcallFuncPtr(name, self)\n" "AttributeError: function ordinal 0 not found\n" ">>>" msgstr "" ">>> cdll.kernel32[1]\n" "<_FuncPtr object at 0x...>\n" ">>> cdll.kernel32[0]\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" " File \"ctypes.py\", line 310, in __getitem__\n" " func = _StdcallFuncPtr(name, self)\n" "AttributeError: function ordinal 0 not found\n" ">>>" #: ../../library/ctypes.rst:150 msgid "Calling functions" msgstr "调用函数" #: ../../library/ctypes.rst:152 msgid "" "You can call these functions like any other Python callable. This example " "uses the ``rand()`` function, which takes no arguments and returns a pseudo-" "random integer::" msgstr "" "你可以像任何其它 Python 可调用对象一样调用这些函数。 这个例子使用了 ``rand()`` 函数,它不接收任何参数并返回一个伪随机整数::" #: ../../library/ctypes.rst:155 msgid "" ">>> print(libc.rand())\n" "1804289383" msgstr "" ">>> print(libc.rand())\n" "1804289383" #: ../../library/ctypes.rst:158 msgid "" "On Windows, you can call the ``GetModuleHandleA()`` function, which returns " "a win32 module handle (passing ``None`` as single argument to call it with a" " ``NULL`` pointer)::" msgstr "" "在 Windows 上,你可以调用 ``GetModuleHandleA()`` 函数,它返回一个 win32 模块句柄 (将 ``None`` " "作为唯一参数传入以使用 ``NULL`` 指针来调用它)::" #: ../../library/ctypes.rst:161 msgid "" ">>> print(hex(windll.kernel32.GetModuleHandleA(None)))\n" "0x1d000000\n" ">>>" msgstr "" ">>> print(hex(windll.kernel32.GetModuleHandleA(None)))\n" "0x1d000000\n" ">>>" #: ../../library/ctypes.rst:165 msgid "" ":exc:`ValueError` is raised when you call an ``stdcall`` function with the " "``cdecl`` calling convention, or vice versa::" msgstr "" "如果你用 ``cdecl`` 调用方式调用 ``stdcall`` 约定的函数,则会甩出一个异常 :exc:`ValueError`。反之亦然。" #: ../../library/ctypes.rst:168 msgid "" ">>> cdll.kernel32.GetModuleHandleA(None)\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "ValueError: Procedure probably called with not enough arguments (4 bytes missing)\n" ">>>\n" "\n" ">>> windll.msvcrt.printf(b\"spam\")\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "ValueError: Procedure probably called with too many arguments (4 bytes in excess)\n" ">>>" msgstr "" ">>> cdll.kernel32.GetModuleHandleA(None)\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "ValueError: Procedure probably called with not enough arguments (4 bytes missing)\n" ">>>\n" "\n" ">>> windll.msvcrt.printf(b\"spam\")\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "ValueError: Procedure probably called with too many arguments (4 bytes in excess)\n" ">>>" #: ../../library/ctypes.rst:180 msgid "" "To find out the correct calling convention you have to look into the C " "header file or the documentation for the function you want to call." msgstr "你必须阅读这些库的头文件或说明文档来确定它们的正确的调用协议。" #: ../../library/ctypes.rst:183 msgid "" "On Windows, :mod:`ctypes` uses win32 structured exception handling to " "prevent crashes from general protection faults when functions are called " "with invalid argument values::" msgstr "在 Windows 中,:mod:`ctypes` 使用 win32 结构化异常处理来防止由于在调用函数时使用非法参数导致的程序崩溃。" #: ../../library/ctypes.rst:187 msgid "" ">>> windll.kernel32.GetModuleHandleA(32)\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "OSError: exception: access violation reading 0x00000020\n" ">>>" msgstr "" ">>> windll.kernel32.GetModuleHandleA(32)\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "OSError: exception: access violation reading 0x00000020\n" ">>>" #: ../../library/ctypes.rst:193 msgid "" "There are, however, enough ways to crash Python with :mod:`ctypes`, so you " "should be careful anyway. The :mod:`faulthandler` module can be helpful in " "debugging crashes (e.g. from segmentation faults produced by erroneous C " "library calls)." msgstr "" "然而,总有许多办法,通过调用 :mod:`ctypes` 使得 Python 程序崩溃。因此,你必须小心使用。 :mod:`faulthandler` " "模块可以用于帮助诊断程序崩溃的原因。(比如由于错误的C库函数调用导致的段错误)。" #: ../../library/ctypes.rst:198 msgid "" "``None``, integers, bytes objects and (unicode) strings are the only native " "Python objects that can directly be used as parameters in these function " "calls. ``None`` is passed as a C ``NULL`` pointer, bytes objects and strings" " are passed as pointer to the memory block that contains their data " "(:c:expr:`char *` or :c:expr:`wchar_t *`). Python integers are passed as " "the platforms default C :c:expr:`int` type, their value is masked to fit " "into the C type." msgstr "" "在原生 Python 对象中,``None``、整数、字节串以及(Unicode)字符串可以直接在这些函数调用中作为参数传递。 ``None`` 作为 " "C 的 ``NULL`` 指针传递,字节串和字符串作为指向包含其数据的内存块的指针传递 (:c:expr:`char *` 或 " ":c:expr:`wchar_t *`)。 Python 整数以平台默认的 C 类型 :c:expr:`int` 传递,它们的值会被掩码化以适应 C " "中的类型。" #: ../../library/ctypes.rst:205 msgid "" "Before we move on calling functions with other parameter types, we have to " "learn more about :mod:`ctypes` data types." msgstr "在我们开始调用函数前,我们必须先了解作为函数参数的 :mod:`ctypes` 数据类型。" #: ../../library/ctypes.rst:212 ../../library/ctypes.rst:2237 msgid "Fundamental data types" msgstr "基础数据类型" #: ../../library/ctypes.rst:214 msgid ":mod:`ctypes` defines a number of primitive C compatible data types:" msgstr ":mod:`ctypes` 定义了一些和C兼容的基本数据类型:" #: ../../library/ctypes.rst:217 msgid "ctypes type" msgstr "ctypes 类型" #: ../../library/ctypes.rst:217 msgid "C type" msgstr "C 类型" #: ../../library/ctypes.rst:217 msgid "Python type" msgstr "Python 类型" #: ../../library/ctypes.rst:219 msgid ":class:`c_bool`" msgstr ":class:`c_bool`" #: ../../library/ctypes.rst:219 msgid ":c:expr:`_Bool`" msgstr ":c:expr:`_Bool`" #: ../../library/ctypes.rst:219 msgid "bool (1)" msgstr "bool (1)" #: ../../library/ctypes.rst:221 msgid ":class:`c_char`" msgstr ":class:`c_char`" #: ../../library/ctypes.rst:221 ../../library/ctypes.rst:225 msgid ":c:expr:`char`" msgstr ":c:expr:`char`" #: ../../library/ctypes.rst:221 msgid "1-character bytes object" msgstr "单字符字节串对象" #: ../../library/ctypes.rst:223 msgid ":class:`c_wchar`" msgstr ":class:`c_wchar`" #: ../../library/ctypes.rst:223 msgid ":c:type:`wchar_t`" msgstr ":c:type:`wchar_t`" #: ../../library/ctypes.rst:223 msgid "1-character string" msgstr "单字符字符串" #: ../../library/ctypes.rst:225 msgid ":class:`c_byte`" msgstr ":class:`c_byte`" #: ../../library/ctypes.rst:225 ../../library/ctypes.rst:227 #: ../../library/ctypes.rst:229 ../../library/ctypes.rst:231 #: ../../library/ctypes.rst:233 ../../library/ctypes.rst:235 #: ../../library/ctypes.rst:237 ../../library/ctypes.rst:239 #: ../../library/ctypes.rst:241 ../../library/ctypes.rst:243 #: ../../library/ctypes.rst:246 ../../library/ctypes.rst:248 #: ../../library/ctypes.rst:251 msgid "int" msgstr "int" #: ../../library/ctypes.rst:227 msgid ":class:`c_ubyte`" msgstr ":class:`c_ubyte`" #: ../../library/ctypes.rst:227 msgid ":c:expr:`unsigned char`" msgstr ":c:expr:`unsigned char`" #: ../../library/ctypes.rst:229 msgid ":class:`c_short`" msgstr ":class:`c_short`" #: ../../library/ctypes.rst:229 msgid ":c:expr:`short`" msgstr ":c:expr:`short`" #: ../../library/ctypes.rst:231 msgid ":class:`c_ushort`" msgstr ":class:`c_ushort`" #: ../../library/ctypes.rst:231 msgid ":c:expr:`unsigned short`" msgstr ":c:expr:`unsigned short`" #: ../../library/ctypes.rst:233 msgid ":class:`c_int`" msgstr ":class:`c_int`" #: ../../library/ctypes.rst:233 msgid ":c:expr:`int`" msgstr ":c:expr:`int`" #: ../../library/ctypes.rst:235 msgid ":class:`c_uint`" msgstr ":class:`c_uint`" #: ../../library/ctypes.rst:235 msgid ":c:expr:`unsigned int`" msgstr ":c:expr:`unsigned int`" #: ../../library/ctypes.rst:237 msgid ":class:`c_long`" msgstr ":class:`c_long`" #: ../../library/ctypes.rst:237 msgid ":c:expr:`long`" msgstr ":c:expr:`long`" #: ../../library/ctypes.rst:239 msgid ":class:`c_ulong`" msgstr ":class:`c_ulong`" #: ../../library/ctypes.rst:239 msgid ":c:expr:`unsigned long`" msgstr ":c:expr:`unsigned long`" #: ../../library/ctypes.rst:241 msgid ":class:`c_longlong`" msgstr ":class:`c_longlong`" #: ../../library/ctypes.rst:241 msgid ":c:expr:`__int64` or :c:expr:`long long`" msgstr ":c:expr:`__int64` 或 :c:expr:`long long`" #: ../../library/ctypes.rst:243 msgid ":class:`c_ulonglong`" msgstr ":class:`c_ulonglong`" #: ../../library/ctypes.rst:243 msgid ":c:expr:`unsigned __int64` or :c:expr:`unsigned long long`" msgstr ":c:expr:`unsigned __int64` 或 :c:expr:`unsigned long long`" #: ../../library/ctypes.rst:246 msgid ":class:`c_size_t`" msgstr ":class:`c_size_t`" #: ../../library/ctypes.rst:246 msgid ":c:type:`size_t`" msgstr ":c:type:`size_t`" #: ../../library/ctypes.rst:248 msgid ":class:`c_ssize_t`" msgstr ":class:`c_ssize_t`" #: ../../library/ctypes.rst:248 msgid ":c:type:`ssize_t` or :c:expr:`Py_ssize_t`" msgstr ":c:type:`ssize_t` 或 :c:expr:`Py_ssize_t`" #: ../../library/ctypes.rst:251 msgid ":class:`c_time_t`" msgstr ":class:`c_time_t`" #: ../../library/ctypes.rst:251 msgid ":c:type:`time_t`" msgstr ":c:type:`time_t`" #: ../../library/ctypes.rst:253 msgid ":class:`c_float`" msgstr ":class:`c_float`" #: ../../library/ctypes.rst:253 msgid ":c:expr:`float`" msgstr ":c:expr:`float`" #: ../../library/ctypes.rst:253 ../../library/ctypes.rst:255 #: ../../library/ctypes.rst:257 msgid "float" msgstr "float" #: ../../library/ctypes.rst:255 msgid ":class:`c_double`" msgstr ":class:`c_double`" #: ../../library/ctypes.rst:255 msgid ":c:expr:`double`" msgstr ":c:expr:`double`" #: ../../library/ctypes.rst:257 msgid ":class:`c_longdouble`" msgstr ":class:`c_longdouble`" #: ../../library/ctypes.rst:257 msgid ":c:expr:`long double`" msgstr ":c:expr:`long double`" #: ../../library/ctypes.rst:259 msgid ":class:`c_char_p`" msgstr ":class:`c_char_p`" #: ../../library/ctypes.rst:259 msgid ":c:expr:`char *` (NUL terminated)" msgstr ":c:expr:`char *` (以 NUL 结尾)" #: ../../library/ctypes.rst:259 msgid "bytes object or ``None``" msgstr "字节串对象或 ``None``" #: ../../library/ctypes.rst:261 msgid ":class:`c_wchar_p`" msgstr ":class:`c_wchar_p`" #: ../../library/ctypes.rst:261 msgid ":c:expr:`wchar_t *` (NUL terminated)" msgstr ":c:expr:`wchar_t *` (以 NUL 结尾)" #: ../../library/ctypes.rst:261 msgid "string or ``None``" msgstr "字符串或 ``None``" #: ../../library/ctypes.rst:263 msgid ":class:`c_void_p`" msgstr ":class:`c_void_p`" #: ../../library/ctypes.rst:263 msgid ":c:expr:`void *`" msgstr ":c:expr:`void *`" #: ../../library/ctypes.rst:263 msgid "int or ``None``" msgstr "int 或 ``None``" #: ../../library/ctypes.rst:267 msgid "The constructor accepts any object with a truth value." msgstr "构造函数接受任何具有真值的对象。" #: ../../library/ctypes.rst:269 msgid "" "All these types can be created by calling them with an optional initializer " "of the correct type and value::" msgstr "所有这些类型都可以通过使用正确类型和值的可选初始值调用它们来创建::" #: ../../library/ctypes.rst:272 msgid "" ">>> c_int()\n" "c_long(0)\n" ">>> c_wchar_p(\"Hello, World\")\n" "c_wchar_p(140018365411392)\n" ">>> c_ushort(-3)\n" "c_ushort(65533)\n" ">>>" msgstr "" ">>> c_int()\n" "c_long(0)\n" ">>> c_wchar_p(\"Hello, World\")\n" "c_wchar_p(140018365411392)\n" ">>> c_ushort(-3)\n" "c_ushort(65533)\n" ">>>" #: ../../library/ctypes.rst:280 msgid "" "Since these types are mutable, their value can also be changed afterwards::" msgstr "由于这些类型是可变的,它们的值也可以在以后更改::" #: ../../library/ctypes.rst:282 msgid "" ">>> i = c_int(42)\n" ">>> print(i)\n" "c_long(42)\n" ">>> print(i.value)\n" "42\n" ">>> i.value = -99\n" ">>> print(i.value)\n" "-99\n" ">>>" msgstr "" ">>> i = c_int(42)\n" ">>> print(i)\n" "c_long(42)\n" ">>> print(i.value)\n" "42\n" ">>> i.value = -99\n" ">>> print(i.value)\n" "-99\n" ">>>" #: ../../library/ctypes.rst:292 msgid "" "Assigning a new value to instances of the pointer types :class:`c_char_p`, " ":class:`c_wchar_p`, and :class:`c_void_p` changes the *memory location* they" " point to, *not the contents* of the memory block (of course not, because " "Python bytes objects are immutable)::" msgstr "" "当给指针类型的对象 :class:`c_char_p`, :class:`c_wchar_p` 和 :class:`c_void_p` " "等赋值时,将改变它们所指向的 *内存地址*,而 *不是* 它们所指向的内存区域的 *内容* (这是理所当然的,因为 Python 的 bytes " "对象是不可变的)::" #: ../../library/ctypes.rst:297 msgid "" ">>> s = \"Hello, World\"\n" ">>> c_s = c_wchar_p(s)\n" ">>> print(c_s)\n" "c_wchar_p(139966785747344)\n" ">>> print(c_s.value)\n" "Hello World\n" ">>> c_s.value = \"Hi, there\"\n" ">>> print(c_s) # the memory location has changed\n" "c_wchar_p(139966783348904)\n" ">>> print(c_s.value)\n" "Hi, there\n" ">>> print(s) # first object is unchanged\n" "Hello, World\n" ">>>" msgstr "" ">>> s = \"Hello, World\"\n" ">>> c_s = c_wchar_p(s)\n" ">>> print(c_s)\n" "c_wchar_p(139966785747344)\n" ">>> print(c_s.value)\n" "Hello World\n" ">>> c_s.value = \"Hi, there\"\n" ">>> print(c_s) # 内存分配已改变\n" "c_wchar_p(139966783348904)\n" ">>> print(c_s.value)\n" "Hi, there\n" ">>> print(s) # 第一个对象未改变\n" "Hello, World\n" ">>>" #: ../../library/ctypes.rst:312 msgid "" "You should be careful, however, not to pass them to functions expecting " "pointers to mutable memory. If you need mutable memory blocks, ctypes has a " ":func:`create_string_buffer` function which creates these in various ways. " "The current memory block contents can be accessed (or changed) with the " "``raw`` property; if you want to access it as NUL terminated string, use the" " ``value`` property::" msgstr "" "但你要注意不能将它们传递给会改变指针所指内存的函数。如果你需要可改变的内存块,ctypes 提供了 " ":func:`create_string_buffer` 函数,它提供多种方式创建这种内存块。当前的内存块内容可以通过 ``raw`` " "属性存取,如果你希望将它作为NUL结束的字符串,请使用 ``value`` 属性::" #: ../../library/ctypes.rst:319 msgid "" ">>> from ctypes import *\n" ">>> p = create_string_buffer(3) # create a 3 byte buffer, initialized to NUL bytes\n" ">>> print(sizeof(p), repr(p.raw))\n" "3 b'\\x00\\x00\\x00'\n" ">>> p = create_string_buffer(b\"Hello\") # create a buffer containing a NUL terminated string\n" ">>> print(sizeof(p), repr(p.raw))\n" "6 b'Hello\\x00'\n" ">>> print(repr(p.value))\n" "b'Hello'\n" ">>> p = create_string_buffer(b\"Hello\", 10) # create a 10 byte buffer\n" ">>> print(sizeof(p), repr(p.raw))\n" "10 b'Hello\\x00\\x00\\x00\\x00\\x00'\n" ">>> p.value = b\"Hi\"\n" ">>> print(sizeof(p), repr(p.raw))\n" "10 b'Hi\\x00lo\\x00\\x00\\x00\\x00\\x00'\n" ">>>" msgstr "" ">>> from ctypes import *\n" ">>> p = create_string_buffer(3) # 创建一个 3 字节的缓冲区,初始化为 NUL 字节\n" ">>> print(sizeof(p), repr(p.raw))\n" "3 b'\\x00\\x00\\x00'\n" ">>> p = create_string_buffer(b\"Hello\") # 创建一个包含以 NUL 结束的字符串的缓冲区\n" ">>> print(sizeof(p), repr(p.raw))\n" "6 b'Hello\\x00'\n" ">>> print(repr(p.value))\n" "b'Hello'\n" ">>> p = create_string_buffer(b\"Hello\", 10) # 创建一个 10 字节的缓冲区\n" ">>> print(sizeof(p), repr(p.raw))\n" "10 b'Hello\\x00\\x00\\x00\\x00\\x00'\n" ">>> p.value = b\"Hi\"\n" ">>> print(sizeof(p), repr(p.raw))\n" "10 b'Hi\\x00lo\\x00\\x00\\x00\\x00\\x00'\n" ">>>" #: ../../library/ctypes.rst:336 msgid "" "The :func:`create_string_buffer` function replaces the old :func:`!c_buffer`" " function (which is still available as an alias). To create a mutable " "memory block containing unicode characters of the C type :c:type:`wchar_t`, " "use the :func:`create_unicode_buffer` function." msgstr "" ":func:`create_string_buffer` 函数取代了旧了 :func:`!c_buffer` 函数(后者仍可作为别名使用)。 " "要创建一个包含 C 类型 :c:type:`wchar_t` 的 unicode 字符的可变内存块,请使用 " ":func:`create_unicode_buffer` 函数。" #: ../../library/ctypes.rst:345 msgid "Calling functions, continued" msgstr "调用函数,继续" #: ../../library/ctypes.rst:347 msgid "" "Note that printf prints to the real standard output channel, *not* to " ":data:`sys.stdout`, so these examples will only work at the console prompt, " "not from within *IDLE* or *PythonWin*::" msgstr "" "注意 printf 将打印到真正标准输出设备,而*不是* :data:`sys.stdout`,因此这些实例只能在控制台提示符下工作,而不能在 " "*IDLE* 或 *PythonWin* 中运行。" #: ../../library/ctypes.rst:351 msgid "" ">>> printf = libc.printf\n" ">>> printf(b\"Hello, %s\\n\", b\"World!\")\n" "Hello, World!\n" "14\n" ">>> printf(b\"Hello, %S\\n\", \"World!\")\n" "Hello, World!\n" "14\n" ">>> printf(b\"%d bottles of beer\\n\", 42)\n" "42 bottles of beer\n" "19\n" ">>> printf(b\"%f bottles of beer\\n\", 42.5)\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "ArgumentError: argument 2: TypeError: Don't know how to convert parameter 2\n" ">>>" msgstr "" #: ../../library/ctypes.rst:367 msgid "" "As has been mentioned before, all Python types except integers, strings, and" " bytes objects have to be wrapped in their corresponding :mod:`ctypes` type," " so that they can be converted to the required C data type::" msgstr "" "正如前面所提到过的,除了整数、字符串以及字节串之外,所有的 Python 类型都必须使用它们对应的 :mod:`ctypes` " "类型包装,才能够被正确地转换为所需的C语言类型。" #: ../../library/ctypes.rst:371 msgid "" ">>> printf(b\"An int %d, a double %f\\n\", 1234, c_double(3.14))\n" "An int 1234, a double 3.140000\n" "31\n" ">>>" msgstr "" ">>> printf(b\"An int %d, a double %f\\n\", 1234, c_double(3.14))\n" "An int 1234, a double 3.140000\n" "31\n" ">>>" #: ../../library/ctypes.rst:379 msgid "Calling variadic functions" msgstr "调用可变函数" #: ../../library/ctypes.rst:381 msgid "" "On a lot of platforms calling variadic functions through ctypes is exactly " "the same as calling functions with a fixed number of parameters. On some " "platforms, and in particular ARM64 for Apple Platforms, the calling " "convention for variadic functions is different than that for regular " "functions." msgstr "" "在许多平台上通过 ctypes 调用可变函数与调用带有固定数量形参的函数是完全一样的。 在某些平台,特别是针对 Apple 平台的 ARM64 " "上,可变函数的调用约定与常规函数则是不同的。" #: ../../library/ctypes.rst:386 msgid "" "On those platforms it is required to specify the :attr:`~_CFuncPtr.argtypes`" " attribute for the regular, non-variadic, function arguments:" msgstr "在这些平台上要求为常规、非可变函数参数指定 :attr:`~_CFuncPtr.argtypes` 属性:" #: ../../library/ctypes.rst:389 msgid "libc.printf.argtypes = [ctypes.c_char_p]" msgstr "libc.printf.argtypes = [ctypes.c_char_p]" #: ../../library/ctypes.rst:393 msgid "" "Because specifying the attribute does not inhibit portability it is advised " "to always specify :attr:`~_CFuncPtr.argtypes` for all variadic functions." msgstr "因为指定该属性不会影响可移植性所以建议总是为所有可变函数指定 :attr:`~_CFuncPtr.argtypes`。" #: ../../library/ctypes.rst:400 msgid "Calling functions with your own custom data types" msgstr "使用自定义的数据类型调用函数" #: ../../library/ctypes.rst:402 msgid "" "You can also customize :mod:`ctypes` argument conversion to allow instances " "of your own classes be used as function arguments. :mod:`ctypes` looks for " "an :attr:`!_as_parameter_` attribute and uses this as the function argument." " The attribute must be an integer, string, bytes, a :mod:`ctypes` instance, " "or an object with an :attr:`!_as_parameter_` attribute::" msgstr "" "您也可以通过自定义 :mod:`ctypes` 参数转换方式来允许将你自己的类实例作为函数参数。 :mod:`ctypes` 会寻找 " ":attr:`!_as_parameter_` 属性并使用它作为函数参数。 属性必须是整数、字符串、字节串、:mod:`ctypes` 实例或者带有 " ":attr:`!_as_parameter_` 属性的对象::" #: ../../library/ctypes.rst:408 msgid "" ">>> class Bottles:\n" "... def __init__(self, number):\n" "... self._as_parameter_ = number\n" "...\n" ">>> bottles = Bottles(42)\n" ">>> printf(b\"%d bottles of beer\\n\", bottles)\n" "42 bottles of beer\n" "19\n" ">>>" msgstr "" ">>> class Bottles:\n" "... def __init__(self, number):\n" "... self._as_parameter_ = number\n" "...\n" ">>> bottles = Bottles(42)\n" ">>> printf(b\"%d bottles of beer\\n\", bottles)\n" "42 bottles of beer\n" "19\n" ">>>" #: ../../library/ctypes.rst:418 msgid "" "If you don't want to store the instance's data in the " ":attr:`!_as_parameter_` instance variable, you could define a " ":class:`property` which makes the attribute available on request." msgstr "" "如果你不想将实例数据存储在 :attr:`!_as_parameter_` 实例变量中,可以定义一个根据请求提供属性的 " ":class:`property`。" #: ../../library/ctypes.rst:426 msgid "Specifying the required argument types (function prototypes)" msgstr "指定必选参数的类型(函数原型)" #: ../../library/ctypes.rst:428 msgid "" "It is possible to specify the required argument types of functions exported " "from DLLs by setting the :attr:`~_CFuncPtr.argtypes` attribute." msgstr "可以通过设置 :attr:`~_CFuncPtr.argtypes` 属性来指定从 DLL 导出函数的必选参数类型。" #: ../../library/ctypes.rst:431 msgid "" ":attr:`~_CFuncPtr.argtypes` must be a sequence of C data types (the " ":func:`!printf` function is 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)::" msgstr "" ":attr:`~_CFuncPtr.argtypes` 必须是一个 C 数据类型的序列(这里 :func:`!printf` " "函数可能不是一个好例子,因为它会根据格式字符串的不同接受可变数量和不同类型的形参,但另一方面这对尝试此功能来说也很方便)::" #: ../../library/ctypes.rst:436 msgid "" ">>> printf.argtypes = [c_char_p, c_char_p, c_int, c_double]\n" ">>> printf(b\"String '%s', Int %d, Double %f\\n\", b\"Hi\", 10, 2.2)\n" "String 'Hi', Int 10, Double 2.200000\n" "37\n" ">>>" msgstr "" ">>> printf.argtypes = [c_char_p, c_char_p, c_int, c_double]\n" ">>> printf(b\"String '%s', Int %d, Double %f\\n\", b\"Hi\", 10, 2.2)\n" "String 'Hi', Int 10, Double 2.200000\n" "37\n" ">>>" #: ../../library/ctypes.rst:442 msgid "" "Specifying a format protects against incompatible argument types (just as a " "prototype for a C function), and tries to convert the arguments to valid " "types::" msgstr "指定数据类型可以防止不合理的参数传递(就像 C 函数的原型),并且会自动尝试将参数转换为需要的类型::" #: ../../library/ctypes.rst:445 msgid "" ">>> printf(b\"%d %d %d\", 1, 2, 3)\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "ArgumentError: argument 2: TypeError: wrong type\n" ">>> printf(b\"%s %d %f\\n\", b\"X\", 2, 3)\n" "X 2 3.000000\n" "13\n" ">>>" msgstr "" #: ../../library/ctypes.rst:454 msgid "" "If you have defined your own classes which you pass to function calls, you " "have to implement a :meth:`~_CData.from_param` class method for them to be " "able to use them in the :attr:`~_CFuncPtr.argtypes` sequence. The " ":meth:`~_CData.from_param` 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 " ":attr:`!_as_parameter_` 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 :mod:`ctypes` instance, or an object with an " ":attr:`!_as_parameter_` attribute." msgstr "" "如果你定义了自己的类并将其传递给函数调用,则你必须为它们实现 :meth:`~_CData.from_param` 类方法才能够在 " ":attr:`~_CFuncPtr.argtypes` 序列中使用它们。 :meth:`~_CData.from_param` " "类方法接受传递给函数调用的 Python 对象,它应该进行类型检查或者其他必要的操作以确保这个对象是可接受的,然后返回对象本身、它的 " ":attr:`!_as_parameter_` 属性,或在此情况下作为 C 函数参数传入的任何东西。 " "同样,结果应该是整数、字符串、字节串、:mod:`ctypes` 实例或是具有 :attr:`!_as_parameter_` 属性的对象。" #: ../../library/ctypes.rst:468 msgid "Return types" msgstr "返回类型" #: ../../library/ctypes.rst:478 msgid "" "By default functions are assumed to return the C :c:expr:`int` type. Other " "return types can be specified by setting the :attr:`~_CFuncPtr.restype` " "attribute of the function object." msgstr "" "在默认情况下都会假定函数返回 C :c:expr:`int` 类型。 其他返回类型可通过设置函数对象的 setting the " ":attr:`~_CFuncPtr.restype` 属性来指定。" #: ../../library/ctypes.rst:482 msgid "" "The C prototype of :c:func:`time` is ``time_t time(time_t *)``. Because " ":c:type:`time_t` might be of a different type than the default return type " ":c:expr:`int`, you should specify the :attr:`!restype` attribute::" msgstr "" ":c:func:`time` 的 C 原型是 ``time_t time(time_t *)``。 由于 :c:type:`time_t` " "的类型可能不同于默认返回类型 :c:expr:`int`,你应当指定 :attr:`!restype` 属性::" #: ../../library/ctypes.rst:486 msgid ">>> libc.time.restype = c_time_t" msgstr ">>> libc.time.restype = c_time_t" #: ../../library/ctypes.rst:488 msgid "" "The argument types can be specified using :attr:`~_CFuncPtr.argtypes`::" msgstr "参数类型可以使用 :attr:`~_CFuncPtr.argtypes` 来指定::" #: ../../library/ctypes.rst:490 msgid ">>> libc.time.argtypes = (POINTER(c_time_t),)" msgstr ">>> libc.time.argtypes = (POINTER(c_time_t),)" #: ../../library/ctypes.rst:492 msgid "" "To call the function with a ``NULL`` pointer as first argument, use " "``None``::" msgstr "调用该函数时如果要将 ``NULL`` 指针作为第一个参数,请使用 ``None``::" #: ../../library/ctypes.rst:494 msgid "" ">>> print(libc.time(None))\n" "1150640792" msgstr "" ">>> print(libc.time(None))\n" "1150640792" #: ../../library/ctypes.rst:497 msgid "" "Here is a more advanced example, it uses the :func:`!strchr` function, which" " expects a string pointer and a char, and returns a pointer to a string::" msgstr "下面是一个更高级的示例,它使用了 :func:`!strchr` 函数,该函数接收一个字符串指针和一个字符,并返回一个字符串指针::" #: ../../library/ctypes.rst:500 msgid "" ">>> strchr = libc.strchr\n" ">>> strchr(b\"abcdef\", ord(\"d\"))\n" "8059983\n" ">>> strchr.restype = c_char_p # c_char_p is a pointer to a string\n" ">>> strchr(b\"abcdef\", ord(\"d\"))\n" "b'def'\n" ">>> print(strchr(b\"abcdef\", ord(\"x\")))\n" "None\n" ">>>" msgstr "" ">>> strchr = libc.strchr\n" ">>> strchr(b\"abcdef\", ord(\"d\"))\n" "8059983\n" ">>> strchr.restype = c_char_p # c_char_p 是一个指向字符串的指针\n" ">>> strchr(b\"abcdef\", ord(\"d\"))\n" "b'def'\n" ">>> print(strchr(b\"abcdef\", ord(\"x\")))\n" "None\n" ">>>" #: ../../library/ctypes.rst:510 msgid "" "If you want to avoid the :func:`ord(\"x\") ` calls above, you can set " "the :attr:`~_CFuncPtr.argtypes` attribute, and the second argument will be " "converted from a single character Python bytes object into a C char:" msgstr "" "如果你想要避免上面的 :func:`ord(\"x\") ` 调用,你可以设置 :attr:`~_CFuncPtr.argtypes` " "属性,第二个参数将从单字符 Python 字节串对象转换为 C char:" #: ../../library/ctypes.rst:514 msgid "" ">>> strchr.restype = c_char_p\n" ">>> strchr.argtypes = [c_char_p, c_char]\n" ">>> strchr(b\"abcdef\", b\"d\")\n" "b'def'\n" ">>> strchr(b\"abcdef\", b\"def\")\n" "Traceback (most recent call last):\n" "ctypes.ArgumentError: argument 2: TypeError: one character bytes, bytearray or integer expected\n" ">>> print(strchr(b\"abcdef\", b\"x\"))\n" "None\n" ">>> strchr(b\"abcdef\", b\"d\")\n" "b'def'\n" ">>>" msgstr "" ">>> strchr.restype = c_char_p\n" ">>> strchr.argtypes = [c_char_p, c_char]\n" ">>> strchr(b\"abcdef\", b\"d\")\n" "b'def'\n" ">>> strchr(b\"abcdef\", b\"def\")\n" "Traceback (most recent call last):\n" "ctypes.ArgumentError: argument 2: TypeError: one character bytes, bytearray or integer expected\n" ">>> print(strchr(b\"abcdef\", b\"x\"))\n" "None\n" ">>> strchr(b\"abcdef\", b\"d\")\n" "b'def'\n" ">>>" #: ../../library/ctypes.rst:529 msgid "" "You can also use a callable Python object (a function or a class for " "example) as the :attr:`~_CFuncPtr.restype` 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::" msgstr "" "如果外部函数返回一个整数,你也可以使用一个 Python 可调用对象(例如函数或类)作为 :attr:`~_CFuncPtr.restype` 属性。 " "该可调用对象被调用时将附带 C 函数返回的 *整数*,其调用结果将被用作函数调用的结果值。 这对于检查错误返回值并自动引发异常来说很有用处::" #: ../../library/ctypes.rst:535 msgid "" ">>> GetModuleHandle = windll.kernel32.GetModuleHandleA\n" ">>> def ValidHandle(value):\n" "... if value == 0:\n" "... raise WinError()\n" "... return value\n" "...\n" ">>>\n" ">>> GetModuleHandle.restype = ValidHandle\n" ">>> GetModuleHandle(None)\n" "486539264\n" ">>> GetModuleHandle(\"something silly\")\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" " File \"\", line 3, in ValidHandle\n" "OSError: [Errno 126] The specified module could not be found.\n" ">>>" msgstr "" ">>> GetModuleHandle = windll.kernel32.GetModuleHandleA\n" ">>> def ValidHandle(value):\n" "... if value == 0:\n" "... raise WinError()\n" "... return value\n" "...\n" ">>>\n" ">>> GetModuleHandle.restype = ValidHandle\n" ">>> GetModuleHandle(None)\n" "486539264\n" ">>> GetModuleHandle(\"something silly\")\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" " File \"\", line 3, in ValidHandle\n" "OSError: [Errno 126] The specified module could not be found.\n" ">>>" #: ../../library/ctypes.rst:552 msgid "" "``WinError`` is a function which will call Windows ``FormatMessage()`` api " "to get the string representation of an error code, and *returns* an " "exception. ``WinError`` takes an optional error code parameter, if no one is" " used, it calls :func:`GetLastError` to retrieve it." msgstr "" "``WinError`` 函数可以调用 Windows 的 ``FormatMessage()`` API 获取错误码的字符串说明,然后 *返回* " "一个异常。 ``WinError`` 接收一个可选的错误码作为参数,如果没有的话,它将调用 :func:`GetLastError` 获取错误码。" #: ../../library/ctypes.rst:557 msgid "" "Please note that a much more powerful error checking mechanism is available " "through the :attr:`~_CFuncPtr.errcheck` attribute; see the reference manual " "for details." msgstr "请注意通过 :attr:`~_CFuncPtr.errcheck` 属性可提供更强大的错误检查机制;详情见参考手册。" #: ../../library/ctypes.rst:565 msgid "Passing pointers (or: passing parameters by reference)" msgstr "传递指针(或以引用方式传递形参)" #: ../../library/ctypes.rst:567 msgid "" "Sometimes a C api function expects a *pointer* to a data type as parameter, " "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*." msgstr "" "有时候 C 函数接口可能由于要往某个地址写入值,或者数据太大不适合作为值传递,从而希望接收一个 *指针* 作为数据参数类型。这和 *传递参数引用* " "类似。" #: ../../library/ctypes.rst:571 msgid "" ":mod:`ctypes` exports the :func:`byref` function which is used to pass " "parameters by reference. The same effect can be achieved with the " ":func:`pointer` function, although :func:`pointer` does a lot more work " "since it constructs a real pointer object, so it is faster to use " ":func:`byref` if you don't need the pointer object in Python itself::" msgstr "" ":mod:`ctypes` 暴露了 :func:`byref` 函数用于通过引用传递参数,使用 :func:`pointer` " "函数也能达到同样的效果,只不过 :func:`pointer` 需要更多步骤,因为它要先构造一个真实指针对象。所以在 Python " "代码本身不需要使用这个指针对象的情况下,使用 :func:`byref` 效率更高。" #: ../../library/ctypes.rst:577 msgid "" ">>> i = c_int()\n" ">>> f = c_float()\n" ">>> s = create_string_buffer(b'\\000' * 32)\n" ">>> print(i.value, f.value, repr(s.value))\n" "0 0.0 b''\n" ">>> libc.sscanf(b\"1 3.14 Hello\", b\"%d %f %s\",\n" "... byref(i), byref(f), s)\n" "3\n" ">>> print(i.value, f.value, repr(s.value))\n" "1 3.1400001049 b'Hello'\n" ">>>" msgstr "" ">>> i = c_int()\n" ">>> f = c_float()\n" ">>> s = create_string_buffer(b'\\000' * 32)\n" ">>> print(i.value, f.value, repr(s.value))\n" "0 0.0 b''\n" ">>> libc.sscanf(b\"1 3.14 Hello\", b\"%d %f %s\",\n" "... byref(i), byref(f), s)\n" "3\n" ">>> print(i.value, f.value, repr(s.value))\n" "1 3.1400001049 b'Hello'\n" ">>>" #: ../../library/ctypes.rst:593 msgid "Structures and unions" msgstr "结构体和联合" #: ../../library/ctypes.rst:595 msgid "" "Structures and unions must derive from the :class:`Structure` and " ":class:`Union` base classes which are defined in the :mod:`ctypes` module. " "Each subclass must define a :attr:`~Structure._fields_` attribute. " ":attr:`!_fields_` must be a list of *2-tuples*, containing a *field name* " "and a *field type*." msgstr "" "结构体和联合必须派生自 :class:`Structure` 和 :class:`Union` 基类,这两个基类是在 :mod:`ctypes` " "模块中定义的。 每个子类都必须定义 :attr:`~Structure._fields_` 属性。 :attr:`!_fields_` 必须是一个 " "*2元组* 的列表,其中包含一个 *字段名称* 和一个 *字段类型*。" #: ../../library/ctypes.rst:600 msgid "" "The field type must be a :mod:`ctypes` type like :class:`c_int`, or any " "other derived :mod:`ctypes` type: structure, union, array, pointer." msgstr "" "type 字段必须是一个 :mod:`ctypes` 类型,比如 :class:`c_int`,或者其他 :mod:`ctypes` 类型: " "结构体、联合、数组、指针。" #: ../../library/ctypes.rst:603 msgid "" "Here is a simple example of a POINT structure, which contains two integers " "named *x* and *y*, and also shows how to initialize a structure in the " "constructor::" msgstr "这是一个简单的 POINT 结构体,它包含名称为 *x* 和 *y* 的两个变量,还展示了如何通过构造函数初始化结构体。" #: ../../library/ctypes.rst:606 msgid "" ">>> from ctypes import *\n" ">>> class POINT(Structure):\n" "... _fields_ = [(\"x\", c_int),\n" "... (\"y\", c_int)]\n" "...\n" ">>> point = POINT(10, 20)\n" ">>> print(point.x, point.y)\n" "10 20\n" ">>> point = POINT(y=5)\n" ">>> print(point.x, point.y)\n" "0 5\n" ">>> POINT(1, 2, 3)\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "TypeError: too many initializers\n" ">>>" msgstr "" ">>> from ctypes import *\n" ">>> class POINT(Structure):\n" "... _fields_ = [(\"x\", c_int),\n" "... (\"y\", c_int)]\n" "...\n" ">>> point = POINT(10, 20)\n" ">>> print(point.x, point.y)\n" "10 20\n" ">>> point = POINT(y=5)\n" ">>> print(point.x, point.y)\n" "0 5\n" ">>> POINT(1, 2, 3)\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "TypeError: too many initializers\n" ">>>" #: ../../library/ctypes.rst:623 msgid "" "You can, however, build much more complicated structures. A structure can " "itself contain other structures by using a structure as a field type." msgstr "当然,你可以构造更复杂的结构体。一个结构体可以通过设置 type 字段包含其他结构体或者自身。" #: ../../library/ctypes.rst:626 msgid "" "Here is a RECT structure which contains two POINTs named *upperleft* and " "*lowerright*::" msgstr "这是以一个 RECT 结构体,他包含了两个 POINT ,分别叫 *upperleft* 和 *lowerright*::" #: ../../library/ctypes.rst:629 msgid "" ">>> class RECT(Structure):\n" "... _fields_ = [(\"upperleft\", POINT),\n" "... (\"lowerright\", POINT)]\n" "...\n" ">>> rc = RECT(point)\n" ">>> print(rc.upperleft.x, rc.upperleft.y)\n" "0 5\n" ">>> print(rc.lowerright.x, rc.lowerright.y)\n" "0 0\n" ">>>" msgstr "" ">>> class RECT(Structure):\n" "... _fields_ = [(\"upperleft\", POINT),\n" "... (\"lowerright\", POINT)]\n" "...\n" ">>> rc = RECT(point)\n" ">>> print(rc.upperleft.x, rc.upperleft.y)\n" "0 5\n" ">>> print(rc.lowerright.x, rc.lowerright.y)\n" "0 0\n" ">>>" #: ../../library/ctypes.rst:640 msgid "" "Nested structures can also be initialized in the constructor in several " "ways::" msgstr "嵌套结构体可以通过几种方式构造初始化::" #: ../../library/ctypes.rst:642 msgid "" ">>> r = RECT(POINT(1, 2), POINT(3, 4))\n" ">>> r = RECT((1, 2), (3, 4))" msgstr "" ">>> r = RECT(POINT(1, 2), POINT(3, 4))\n" ">>> r = RECT((1, 2), (3, 4))" #: ../../library/ctypes.rst:645 msgid "" "Field :term:`descriptor`\\s can be retrieved from the *class*, they are " "useful for debugging because they can provide useful information::" msgstr "可以通过 *类* 获取字段 :term:`descriptor` ,它能提供很多有用的调试信息。" #: ../../library/ctypes.rst:648 msgid "" ">>> print(POINT.x)\n" "\n" ">>> print(POINT.y)\n" "\n" ">>>" msgstr "" ">>> print(POINT.x)\n" "\n" ">>> print(POINT.y)\n" "\n" ">>>" #: ../../library/ctypes.rst:659 msgid "" ":mod:`ctypes` does not support passing unions or structures with bit-fields " "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." msgstr "" ":mod:`ctypes` 不支持带位域的结构体、联合以值的方式传给函数。这可能在 32 位 x86 " "平台上可以正常工作,但是对于一般情况,这种行为是未定义的。带位域的结构体、联合应该总是通过指针传递给函数。" #: ../../library/ctypes.rst:665 msgid "Structure/union alignment and byte order" msgstr "结构体/联合字段对齐及字节顺序" #: ../../library/ctypes.rst:667 msgid "" "By default, Structure and Union fields are aligned in the same way the C " "compiler does it. It is possible to override this behavior by specifying a " ":attr:`~Structure._pack_` 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 ``#pragma pack(n)`` also does in MSVC." msgstr "" "在默认情况下,Structure 和 Union 的字段使用与 C 编译器一样的方式进行对齐。 可以通过在子类定义中指定 " ":attr:`~Structure._pack_` 类属性来修改此行为。 该属性必须设为一个正整数来指明字段对齐的最大值。 这也是 ``#pragma " "pack(n)`` 在 MSVC 中的行为。" #: ../../library/ctypes.rst:673 msgid "" ":mod:`ctypes` uses the native byte order for Structures and Unions. To " "build structures with non-native byte order, you can use one of the " ":class:`BigEndianStructure`, :class:`LittleEndianStructure`, " ":class:`BigEndianUnion`, and :class:`LittleEndianUnion` base classes. These" " classes cannot contain pointer fields." msgstr "" ":mod:`ctypes` 中的结构体和联合使用的是本地字节序。要使用非本地字节序,可以使用 :class:`BigEndianStructure`, " ":class:`LittleEndianStructure`, :class:`BigEndianUnion`, and " ":class:`LittleEndianUnion` 作为基类。这些类不能包含指针字段。" #: ../../library/ctypes.rst:683 msgid "Bit fields in structures and unions" msgstr "结构体和联合中的位域" #: ../../library/ctypes.rst:685 msgid "" "It is possible to create structures and unions containing bit fields. Bit " "fields are only possible for integer fields, the bit width is specified as " "the third item in the :attr:`~Structure._fields_` tuples::" msgstr "" "可以创建包含位字段的结构体和联合。 位字段只适用于整数字段,位宽度是由 :attr:`~Structure._fields_` " "元组中的第三项来指定的::" #: ../../library/ctypes.rst:689 msgid "" ">>> class Int(Structure):\n" "... _fields_ = [(\"first_16\", c_int, 16),\n" "... (\"second_16\", c_int, 16)]\n" "...\n" ">>> print(Int.first_16)\n" "\n" ">>> print(Int.second_16)\n" "\n" ">>>" msgstr "" ">>> class Int(Structure):\n" "... _fields_ = [(\"first_16\", c_int, 16),\n" "... (\"second_16\", c_int, 16)]\n" "...\n" ">>> print(Int.first_16)\n" "\n" ">>> print(Int.second_16)\n" "\n" ">>>" #: ../../library/ctypes.rst:703 msgid "Arrays" msgstr "数组" #: ../../library/ctypes.rst:705 msgid "" "Arrays are sequences, containing a fixed number of instances of the same " "type." msgstr "数组是一个序列,包含指定个数元素,且必须类型相同。" #: ../../library/ctypes.rst:707 msgid "" "The recommended way to create array types is by multiplying a data type with" " a positive integer::" msgstr "创建数组类型的推荐方式是使用一个类型乘以一个正数::" #: ../../library/ctypes.rst:710 msgid "TenPointsArrayType = POINT * 10" msgstr "TenPointsArrayType = POINT * 10" #: ../../library/ctypes.rst:712 msgid "" "Here is an example of a somewhat artificial data type, a structure " "containing 4 POINTs among other stuff::" msgstr "下面是一个构造的数据案例,结构体中包含了4个 POINT 和一些其他东西。" #: ../../library/ctypes.rst:715 msgid "" ">>> from ctypes import *\n" ">>> class POINT(Structure):\n" "... _fields_ = (\"x\", c_int), (\"y\", c_int)\n" "...\n" ">>> class MyStruct(Structure):\n" "... _fields_ = [(\"a\", c_int),\n" "... (\"b\", c_float),\n" "... (\"point_array\", POINT * 4)]\n" ">>>\n" ">>> print(len(MyStruct().point_array))\n" "4\n" ">>>" msgstr "" ">>> from ctypes import *\n" ">>> class POINT(Structure):\n" "... _fields_ = (\"x\", c_int), (\"y\", c_int)\n" "...\n" ">>> class MyStruct(Structure):\n" "... _fields_ = [(\"a\", c_int),\n" "... (\"b\", c_float),\n" "... (\"point_array\", POINT * 4)]\n" ">>>\n" ">>> print(len(MyStruct().point_array))\n" "4\n" ">>>" #: ../../library/ctypes.rst:728 msgid "Instances are created in the usual way, by calling the class::" msgstr "和平常一样,通过调用它创建实例::" #: ../../library/ctypes.rst:730 msgid "" "arr = TenPointsArrayType()\n" "for pt in arr:\n" " print(pt.x, pt.y)" msgstr "" "arr = TenPointsArrayType()\n" "for pt in arr:\n" " print(pt.x, pt.y)" #: ../../library/ctypes.rst:734 msgid "" "The above code print a series of ``0 0`` lines, because the array contents " "is initialized to zeros." msgstr "以上代码会打印几行 ``0 0`` ,因为数组内容被初始化为 0." #: ../../library/ctypes.rst:737 msgid "Initializers of the correct type can also be specified::" msgstr "也能通过指定正确类型的数据来初始化::" #: ../../library/ctypes.rst:739 msgid "" ">>> from ctypes import *\n" ">>> TenIntegers = c_int * 10\n" ">>> ii = TenIntegers(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)\n" ">>> print(ii)\n" "\n" ">>> for i in ii: print(i, end=\" \")\n" "...\n" "1 2 3 4 5 6 7 8 9 10\n" ">>>" msgstr "" ">>> from ctypes import *\n" ">>> TenIntegers = c_int * 10\n" ">>> ii = TenIntegers(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)\n" ">>> print(ii)\n" "\n" ">>> for i in ii: print(i, end=\" \")\n" "...\n" "1 2 3 4 5 6 7 8 9 10\n" ">>>" #: ../../library/ctypes.rst:753 msgid "Pointers" msgstr "指针" #: ../../library/ctypes.rst:755 msgid "" "Pointer instances are created by calling the :func:`pointer` function on a " ":mod:`ctypes` type::" msgstr "可以将 :mod:`ctypes` 类型数据传入 :func:`pointer` 函数创建指针::" #: ../../library/ctypes.rst:758 msgid "" ">>> from ctypes import *\n" ">>> i = c_int(42)\n" ">>> pi = pointer(i)\n" ">>>" msgstr "" ">>> from ctypes import *\n" ">>> i = c_int(42)\n" ">>> pi = pointer(i)\n" ">>>" #: ../../library/ctypes.rst:763 msgid "" "Pointer instances have a :attr:`~_Pointer.contents` attribute which returns " "the object to which the pointer points, the ``i`` object above::" msgstr "指针实例拥有 :attr:`~_Pointer.contents` 属性,它返回指针指向的真实对象,如上面的 ``i`` 对象::" #: ../../library/ctypes.rst:766 msgid "" ">>> pi.contents\n" "c_long(42)\n" ">>>" msgstr "" ">>> pi.contents\n" "c_long(42)\n" ">>>" #: ../../library/ctypes.rst:770 msgid "" "Note that :mod:`ctypes` does not have OOR (original object return), it " "constructs a new, equivalent object each time you retrieve an attribute::" msgstr "注意 :mod:`ctypes` 并没有 OOR (返回原始对象), 每次访问这个属性时都会构造返回一个新的相同对象::" #: ../../library/ctypes.rst:773 msgid "" ">>> pi.contents is i\n" "False\n" ">>> pi.contents is pi.contents\n" "False\n" ">>>" msgstr "" ">>> pi.contents is i\n" "False\n" ">>> pi.contents is pi.contents\n" "False\n" ">>>" #: ../../library/ctypes.rst:779 msgid "" "Assigning another :class:`c_int` instance to the pointer's contents " "attribute would cause the pointer to point to the memory location where this" " is stored::" msgstr "将这个指针的 contents 属性赋值为另一个 :class:`c_int` 实例将会导致该指针指向该实例的内存地址::" #: ../../library/ctypes.rst:782 msgid "" ">>> i = c_int(99)\n" ">>> pi.contents = i\n" ">>> pi.contents\n" "c_long(99)\n" ">>>" msgstr "" ">>> i = c_int(99)\n" ">>> pi.contents = i\n" ">>> pi.contents\n" "c_long(99)\n" ">>>" #: ../../library/ctypes.rst:791 msgid "Pointer instances can also be indexed with integers::" msgstr "指针对象也可以通过整数下标进行访问::" #: ../../library/ctypes.rst:793 msgid "" ">>> pi[0]\n" "99\n" ">>>" msgstr "" ">>> pi[0]\n" "99\n" ">>>" #: ../../library/ctypes.rst:797 msgid "Assigning to an integer index changes the pointed to value::" msgstr "通过整数下标赋值可以改变指针所指向的真实内容::" #: ../../library/ctypes.rst:799 msgid "" ">>> print(i)\n" "c_long(99)\n" ">>> pi[0] = 22\n" ">>> print(i)\n" "c_long(22)\n" ">>>" msgstr "" ">>> print(i)\n" "c_long(99)\n" ">>> pi[0] = 22\n" ">>> print(i)\n" "c_long(22)\n" ">>>" #: ../../library/ctypes.rst:806 msgid "" "It is also possible to use indexes different from 0, but you must know what " "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." msgstr "" "使用 0 以外的索引也是合法的,但是你必须确保知道自己为什么这么做,就像 C 语言中: 你可以访问或者修改任意内存内容。 " "通常只会在函数接收指针是才会使用这种特性,而且你 *知道* 这个指针指向的是一个数组而不是单个值。" #: ../../library/ctypes.rst:812 msgid "" "Behind the scenes, the :func:`pointer` function does more than simply create" " pointer instances, it has to create pointer *types* first. This is done " "with the :func:`POINTER` function, which accepts any :mod:`ctypes` type, and" " returns a new type::" msgstr "" "内部细节, :func:`pointer` 函数不只是创建了一个指针实例,它首先创建了一个指针 *类型* 。这是通过调用 " ":func:`POINTER` 函数实现的,它接收 :mod:`ctypes` 类型为参数,返回一个新的类型::" #: ../../library/ctypes.rst:817 msgid "" ">>> PI = POINTER(c_int)\n" ">>> PI\n" "\n" ">>> PI(42)\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "TypeError: expected c_long instead of int\n" ">>> PI(c_int(42))\n" "\n" ">>>" msgstr "" ">>> PI = POINTER(c_int)\n" ">>> PI\n" "\n" ">>> PI(42)\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "TypeError: expected c_long instead of int\n" ">>> PI(c_int(42))\n" "\n" ">>>" #: ../../library/ctypes.rst:828 msgid "" "Calling the pointer type without an argument creates a ``NULL`` pointer. " "``NULL`` pointers have a ``False`` boolean value::" msgstr "无参调用指针类型可以创建一个 ``NULL`` 指针。 ``NULL`` 指针的布尔值是 ``False`` ::" #: ../../library/ctypes.rst:831 msgid "" ">>> null_ptr = POINTER(c_int)()\n" ">>> print(bool(null_ptr))\n" "False\n" ">>>" msgstr "" ">>> null_ptr = POINTER(c_int)()\n" ">>> print(bool(null_ptr))\n" "False\n" ">>>" #: ../../library/ctypes.rst:836 msgid "" ":mod:`ctypes` checks for ``NULL`` when dereferencing pointers (but " "dereferencing invalid non-\\ ``NULL`` pointers would crash Python)::" msgstr "" "解引用指针的时候, :mod:`ctypes` 会帮你检测是否指针为 ``NULL`` (但是解引用无效的 非 ``NULL`` 指针仍会导致 " "Python 崩溃)::" #: ../../library/ctypes.rst:839 msgid "" ">>> null_ptr[0]\n" "Traceback (most recent call last):\n" " ....\n" "ValueError: NULL pointer access\n" ">>>\n" "\n" ">>> null_ptr[0] = 1234\n" "Traceback (most recent call last):\n" " ....\n" "ValueError: NULL pointer access\n" ">>>" msgstr "" ">>> null_ptr[0]\n" "Traceback (most recent call last):\n" " ....\n" "ValueError: NULL pointer access\n" ">>>\n" "\n" ">>> null_ptr[0] = 1234\n" "Traceback (most recent call last):\n" " ....\n" "ValueError: NULL pointer access\n" ">>>" #: ../../library/ctypes.rst:855 msgid "Type conversions" msgstr "类型转换" #: ../../library/ctypes.rst:857 msgid "" "Usually, ctypes does strict type checking. This means, if you have " "``POINTER(c_int)`` in the :attr:`~_CFuncPtr.argtypes` 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 ``POINTER(c_int)``, " "ctypes accepts an array of c_int::" msgstr "" "通常,ctypes 会进行严格的类型检查。 这意味着,如果在某个函数的 :attr:`~_CFuncPtr.argtypes` 列表中有 " "``POINTER(c_int)`` 或在结构体定义中将其用作成员字段的类型,则只接受完全相同类型的实例。 此规则也有一些例外情况,在这些情况下 " "ctypes 可以接受其他对象。 例如,你可以传入兼容的数组实例而不是指针类型。 因此,对于 ``POINTER(c_int)``,ctypes " "接受一个 c_int 数组::" #: ../../library/ctypes.rst:864 msgid "" ">>> class Bar(Structure):\n" "... _fields_ = [(\"count\", c_int), (\"values\", POINTER(c_int))]\n" "...\n" ">>> bar = Bar()\n" ">>> bar.values = (c_int * 3)(1, 2, 3)\n" ">>> bar.count = 3\n" ">>> for i in range(bar.count):\n" "... print(bar.values[i])\n" "...\n" "1\n" "2\n" "3\n" ">>>" msgstr "" ">>> class Bar(Structure):\n" "... _fields_ = [(\"count\", c_int), (\"values\", POINTER(c_int))]\n" "...\n" ">>> bar = Bar()\n" ">>> bar.values = (c_int * 3)(1, 2, 3)\n" ">>> bar.count = 3\n" ">>> for i in range(bar.count):\n" "... print(bar.values[i])\n" "...\n" "1\n" "2\n" "3\n" ">>>" #: ../../library/ctypes.rst:878 msgid "" "In addition, if a function argument is explicitly declared to be a pointer " "type (such as ``POINTER(c_int)``) in :attr:`~_CFuncPtr.argtypes`, an object " "of the pointed type (``c_int`` in this case) can be passed to the function." " ctypes will apply the required :func:`byref` conversion in this case " "automatically." msgstr "" "此外,如果一个函数参数在 :attr:`~_CFuncPtr.argtypes` 中显式地声明为指针类型 (如 " "``POINTER(c_int)``),则可以向该函数传递所指向的类型的对象 (在本例 中为 ``c_int``)。 在这种情况下,ctypes " "将自动应用所需的 :func:`byref` 转换。conversion in this case automatically." #: ../../library/ctypes.rst:883 msgid "To set a POINTER type field to ``NULL``, you can assign ``None``::" msgstr "可以给指针内容赋值为 None 将其设置为 ``Null`` ::" #: ../../library/ctypes.rst:885 msgid "" ">>> bar.values = None\n" ">>>" msgstr "" ">>> bar.values = None\n" ">>>" #: ../../library/ctypes.rst:890 msgid "" "Sometimes you have instances of incompatible types. In C, you can cast one " "type into another type. :mod:`ctypes` provides a :func:`cast` function " "which can be used in the same way. The ``Bar`` structure defined above " "accepts ``POINTER(c_int)`` pointers or :class:`c_int` arrays for its " "``values`` field, but not instances of other types::" msgstr "" "有时候你拥有一个不兼容的类型。 在 C 中,你可以将一个类型强制转换为另一个。 :mod:`ctypes` 中的 a :func:`cast` " "函数提供了相同的功能。 上面的结构体 ``Bar`` 的 ``value`` 字段接收 ``POINTER(c_int)`` 指针或者 " ":class:`c_int` 数组,但是不能接受其他类型的实例::" #: ../../library/ctypes.rst:896 msgid "" ">>> bar.values = (c_byte * 4)()\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "TypeError: incompatible types, c_byte_Array_4 instance instead of LP_c_long instance\n" ">>>" msgstr "" ">>> bar.values = (c_byte * 4)()\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" "TypeError: incompatible types, c_byte_Array_4 instance instead of LP_c_long instance\n" ">>>" #: ../../library/ctypes.rst:902 msgid "For these cases, the :func:`cast` function is handy." msgstr "这种情况下, 需要手动使用 :func:`cast` 函数。" #: ../../library/ctypes.rst:904 msgid "" "The :func:`cast` function can be used to cast a ctypes instance into a " "pointer to a different ctypes data type. :func:`cast` 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::" msgstr "" ":func:`cast` 函数可以将一个指针实例强制转换为另一种 ctypes 类型。 :func:`cast` 接收两个参数,一个 ctypes " "指针对象或者可以被转换为指针的其他类型对象,和一个 ctypes 指针类型。 返回第二个类型的一个实例,该返回实例和第一个参数指向同一片内存空间::" #: ../../library/ctypes.rst:910 msgid "" ">>> a = (c_byte * 4)()\n" ">>> cast(a, POINTER(c_int))\n" "\n" ">>>" msgstr "" ">>> a = (c_byte * 4)()\n" ">>> cast(a, POINTER(c_int))\n" "\n" ">>>" #: ../../library/ctypes.rst:915 msgid "" "So, :func:`cast` can be used to assign to the ``values`` field of ``Bar`` " "the structure::" msgstr "所以 :func:`cast` 可以用来给结构体 ``Bar`` 的 ``values`` 字段赋值::" #: ../../library/ctypes.rst:918 msgid "" ">>> bar = Bar()\n" ">>> bar.values = cast((c_byte * 4)(), POINTER(c_int))\n" ">>> print(bar.values[0])\n" "0\n" ">>>" msgstr "" ">>> bar = Bar()\n" ">>> bar.values = cast((c_byte * 4)(), POINTER(c_int))\n" ">>> print(bar.values[0])\n" "0\n" ">>>" #: ../../library/ctypes.rst:928 msgid "Incomplete Types" msgstr "不完整类型" #: ../../library/ctypes.rst:930 msgid "" "*Incomplete Types* are structures, unions or arrays whose members are not " "yet specified. In C, they are specified by forward declarations, which are " "defined later::" msgstr "*不完整类型* 即还没有定义成员的结构体、联合或者数组。在 C 中,它们通常用于前置声明,然后在后面定义::" #: ../../library/ctypes.rst:934 msgid "" "struct cell; /* forward declaration */\n" "\n" "struct cell {\n" " char *name;\n" " struct cell *next;\n" "};" msgstr "" "struct cell; /* 前向声明 */\n" "\n" "struct cell {\n" " char *name;\n" " struct cell *next;\n" "};" #: ../../library/ctypes.rst:941 msgid "" "The straightforward translation into ctypes code would be this, but it does " "not work::" msgstr "直接翻译成 ctypes 的代码如下,但是这行不通::" #: ../../library/ctypes.rst:944 msgid "" ">>> class cell(Structure):\n" "... _fields_ = [(\"name\", c_char_p),\n" "... (\"next\", POINTER(cell))]\n" "...\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" " File \"\", line 2, in cell\n" "NameError: name 'cell' is not defined\n" ">>>" msgstr "" ">>> class cell(Structure):\n" "... _fields_ = [(\"name\", c_char_p),\n" "... (\"next\", POINTER(cell))]\n" "...\n" "Traceback (most recent call last):\n" " File \"\", line 1, in \n" " File \"\", line 2, in cell\n" "NameError: name 'cell' is not defined\n" ">>>" #: ../../library/ctypes.rst:954 msgid "" "because the new ``class cell`` is not available in the class statement " "itself. In :mod:`ctypes`, we can define the ``cell`` class and set the " ":attr:`~Structure._fields_` attribute later, after the class statement::" msgstr "" "因为新的 ``class cell`` 在 class 语句本身中是不可用的。 在 :mod:`ctypes` 中,我们可以定义 ``cell`` " "类再在 class 语句之后设置 :attr:`~Structure._fields_` 属性::" #: ../../library/ctypes.rst:958 msgid "" ">>> from ctypes import *\n" ">>> class cell(Structure):\n" "... pass\n" "...\n" ">>> cell._fields_ = [(\"name\", c_char_p),\n" "... (\"next\", POINTER(cell))]\n" ">>>" msgstr "" ">>> from ctypes import *\n" ">>> class cell(Structure):\n" "... pass\n" "...\n" ">>> cell._fields_ = [(\"name\", c_char_p),\n" "... (\"next\", POINTER(cell))]\n" ">>>" #: ../../library/ctypes.rst:966 msgid "" "Let's try it. We create two instances of ``cell``, and let them point to " "each other, and finally follow the pointer chain a few times::" msgstr "让我们试试。我们定义两个 ``cell`` 实例,让它们互相指向对方,然后通过指针链式访问几次::" #: ../../library/ctypes.rst:969 msgid "" ">>> c1 = cell()\n" ">>> c1.name = b\"foo\"\n" ">>> c2 = cell()\n" ">>> c2.name = b\"bar\"\n" ">>> c1.next = pointer(c2)\n" ">>> c2.next = pointer(c1)\n" ">>> p = c1\n" ">>> for i in range(8):\n" "... print(p.name, end=\" \")\n" "... p = p.next[0]\n" "...\n" "foo bar foo bar foo bar foo bar\n" ">>>" msgstr "" ">>> c1 = cell()\n" ">>> c1.name = b\"foo\"\n" ">>> c2 = cell()\n" ">>> c2.name = b\"bar\"\n" ">>> c1.next = pointer(c2)\n" ">>> c2.next = pointer(c1)\n" ">>> p = c1\n" ">>> for i in range(8):\n" "... print(p.name, end=\" \")\n" "... p = p.next[0]\n" "...\n" "foo bar foo bar foo bar foo bar\n" ">>>" #: ../../library/ctypes.rst:987 msgid "Callback functions" msgstr "回调函数" #: ../../library/ctypes.rst:989 msgid "" ":mod:`ctypes` allows creating C callable function pointers from Python " "callables. These are sometimes called *callback functions*." msgstr ":mod:`ctypes` 允许创建一个指向 Python 可调用对象的 C 函数。它们有时候被称为 *回调函数* 。" #: ../../library/ctypes.rst:992 msgid "" "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." msgstr "首先,你必须为回调函数创建一个类,这个类知道调用约定,包括返回值类型以及函数接收的参数类型及个数。" #: ../../library/ctypes.rst:996 msgid "" "The :func:`CFUNCTYPE` factory function creates types for callback functions " "using the ``cdecl`` calling convention. On Windows, the :func:`WINFUNCTYPE` " "factory function creates types for callback functions using the ``stdcall`` " "calling convention." msgstr "" ":func:`CFUNCTYPE` 工厂函数使用 ``cdecl`` 调用约定创建回调函数类型。在 Windows 上, " ":func:`WINFUNCTYPE` 工厂函数使用 ``stdcall`` 调用约定为回调函数创建类型。" #: ../../library/ctypes.rst:1001 msgid "" "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." msgstr "这些工厂函数的第一个参数是返回值类型,回调函数的参数类型作为剩余参数。" #: ../../library/ctypes.rst:1005 msgid "" "I will present an example here which uses the standard C library's " ":c:func:`!qsort` function, that is used to sort items with the help of a " "callback function. :c:func:`!qsort` will be used to sort an array of " "integers::" msgstr "" "这里展示一个使用标准 C 库的 :c:func:`!qsort` 函数例子,使用它在一个回调函数的协助下对条目进行排序。 " ":c:func:`!qsort` 将被用来给一个整数的数组排序::" #: ../../library/ctypes.rst:1009 msgid "" ">>> IntArray5 = c_int * 5\n" ">>> ia = IntArray5(5, 1, 7, 33, 99)\n" ">>> qsort = libc.qsort\n" ">>> qsort.restype = None\n" ">>>" msgstr "" ">>> IntArray5 = c_int * 5\n" ">>> ia = IntArray5(5, 1, 7, 33, 99)\n" ">>> qsort = libc.qsort\n" ">>> qsort.restype = None\n" ">>>" #: ../../library/ctypes.rst:1015 msgid "" ":func:`!qsort` must be called with a pointer to the data to sort, the number" " of items in the data array, the size of one item, and a pointer to the " "comparison function, the callback. 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." msgstr "" ":func:`!qsort` 被调用时必须传入一个指向要排序的数据的指针、数据数组中的条目数、每条目的大小以及一个指向比较函数即回调函数的指针。 " "回调函数将附带两个指向条目的指针进行调用,如果第一个条目小于第二个条目则它必须返回一个负整数,如果两者相等则返回零,在其他情况下则返回一个正整数。" #: ../../library/ctypes.rst:1021 msgid "" "So our callback function receives pointers to integers, and must return an " "integer. First we create the ``type`` for the callback function::" msgstr "所以,我们的回调函数要接收两个整数指针,返回一个整数。首先我们创建回调函数的 ``类型`` ::" #: ../../library/ctypes.rst:1024 msgid "" ">>> CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))\n" ">>>" msgstr "" ">>> CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))\n" ">>>" #: ../../library/ctypes.rst:1027 msgid "" "To get started, here is a simple callback that shows the values it gets " "passed::" msgstr "首先,这是一个简单的回调,它会显示传入的值::" #: ../../library/ctypes.rst:1030 msgid "" ">>> def py_cmp_func(a, b):\n" "... print(\"py_cmp_func\", a[0], b[0])\n" "... return 0\n" "...\n" ">>> cmp_func = CMPFUNC(py_cmp_func)\n" ">>>" msgstr "" ">>> def py_cmp_func(a, b):\n" "... print(\"py_cmp_func\", a[0], b[0])\n" "... return 0\n" "...\n" ">>> cmp_func = CMPFUNC(py_cmp_func)\n" ">>>" #: ../../library/ctypes.rst:1037 msgid "The result::" msgstr "结果::" #: ../../library/ctypes.rst:1039 msgid "" ">>> qsort(ia, len(ia), sizeof(c_int), cmp_func)\n" "py_cmp_func 5 1\n" "py_cmp_func 33 99\n" "py_cmp_func 7 33\n" "py_cmp_func 5 7\n" "py_cmp_func 1 7\n" ">>>" msgstr "" ">>> qsort(ia, len(ia), sizeof(c_int), cmp_func)\n" "py_cmp_func 5 1\n" "py_cmp_func 33 99\n" "py_cmp_func 7 33\n" "py_cmp_func 5 7\n" "py_cmp_func 1 7\n" ">>>" #: ../../library/ctypes.rst:1047 msgid "Now we can actually compare the two items and return a useful result::" msgstr "现在我们可以比较两个元素并返回有用的结果了::" #: ../../library/ctypes.rst:1049 msgid "" ">>> def py_cmp_func(a, b):\n" "... print(\"py_cmp_func\", a[0], b[0])\n" "... return a[0] - b[0]\n" "...\n" ">>>\n" ">>> qsort(ia, len(ia), sizeof(c_int), CMPFUNC(py_cmp_func))\n" "py_cmp_func 5 1\n" "py_cmp_func 33 99\n" "py_cmp_func 7 33\n" "py_cmp_func 1 7\n" "py_cmp_func 5 7\n" ">>>" msgstr "" ">>> def py_cmp_func(a, b):\n" "... print(\"py_cmp_func\", a[0], b[0])\n" "... return a[0] - b[0]\n" "...\n" ">>>\n" ">>> qsort(ia, len(ia), sizeof(c_int), CMPFUNC(py_cmp_func))\n" "py_cmp_func 5 1\n" "py_cmp_func 33 99\n" "py_cmp_func 7 33\n" "py_cmp_func 1 7\n" "py_cmp_func 5 7\n" ">>>" #: ../../library/ctypes.rst:1062 msgid "As we can easily check, our array is sorted now::" msgstr "我们可以轻易地验证,现在数组是有序的了::" #: ../../library/ctypes.rst:1064 msgid "" ">>> for i in ia: print(i, end=\" \")\n" "...\n" "1 5 7 33 99\n" ">>>" msgstr "" ">>> for i in ia: print(i, end=\" \")\n" "...\n" "1 5 7 33 99\n" ">>>" #: ../../library/ctypes.rst:1069 msgid "" "The function factories can be used as decorator factories, so we may as well" " write::" msgstr "这些工厂函数可以当作装饰器工厂,所以可以这样写::" #: ../../library/ctypes.rst:1072 msgid "" ">>> @CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))\n" "... def py_cmp_func(a, b):\n" "... print(\"py_cmp_func\", a[0], b[0])\n" "... return a[0] - b[0]\n" "...\n" ">>> qsort(ia, len(ia), sizeof(c_int), py_cmp_func)\n" "py_cmp_func 5 1\n" "py_cmp_func 33 99\n" "py_cmp_func 7 33\n" "py_cmp_func 1 7\n" "py_cmp_func 5 7\n" ">>>" msgstr "" ">>> @CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))\n" "... def py_cmp_func(a, b):\n" "... print(\"py_cmp_func\", a[0], b[0])\n" "... return a[0] - b[0]\n" "...\n" ">>> qsort(ia, len(ia), sizeof(c_int), py_cmp_func)\n" "py_cmp_func 5 1\n" "py_cmp_func 33 99\n" "py_cmp_func 7 33\n" "py_cmp_func 1 7\n" "py_cmp_func 5 7\n" ">>>" #: ../../library/ctypes.rst:1087 msgid "" "Make sure you keep references to :func:`CFUNCTYPE` objects as long as they " "are used from C code. :mod:`ctypes` doesn't, and if you don't, they may be " "garbage collected, crashing your program when a callback is made." msgstr "" "请确保你维持的 :func:`CFUNCTYPE` 对象的引用周期与它们在 C 代码中的使用期一样长。 :mod:`ctypes` " "不会确保这一点,如果不这样做,它们可能会被垃圾回收,导致程序在执行回调函数时发生崩溃。" #: ../../library/ctypes.rst:1091 msgid "" "Also, note that if the callback function is called in a thread created " "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 :class:`threading.local` will *not* survive across different callbacks," " even when those calls are made from the same C thread." msgstr "" "注意,如果回调函数在Python之外的另外一个线程使用(比如,外部代码调用这个回调函数), ctypes 会在每一次调用上创建一个虚拟 Python " "线程。这个行为在大多数情况下是合理的,但也意味着如果有数据使用 :class:`threading.local` " "方式存储,将无法访问,就算它们是在同一个 C 线程中调用的 。" #: ../../library/ctypes.rst:1101 msgid "Accessing values exported from dlls" msgstr "访问 dll 的导出变量" #: ../../library/ctypes.rst:1103 msgid "" "Some shared libraries not only export functions, they also export variables." " An example in the Python library itself is the :c:data:`Py_Version`, Python" " runtime version number encoded in a single constant integer." msgstr "" "某些共享库不仅会导出函数,还会导出变量。 一个例子就是 Python 库本身的 :c:data:`Py_Version`,Python " "运行时版本号被编码为单个整数常量。" #: ../../library/ctypes.rst:1107 msgid "" ":mod:`ctypes` can access values like this with the :meth:`~_CData.in_dll` " "class methods of the type. *pythonapi* is a predefined symbol giving access" " to the Python C api::" msgstr "" ":mod:`ctypes` 可以通过类型的 :meth:`~_CData.in_dll` 类方法访问这样的值。 *pythonapi* 是一个用于访问 " "Python C api 预定义符号::" #: ../../library/ctypes.rst:1111 msgid "" ">>> version = ctypes.c_int.in_dll(ctypes.pythonapi, \"Py_Version\")\n" ">>> print(hex(version.value))\n" "0x30c00a0" msgstr "" ">>> version = ctypes.c_int.in_dll(ctypes.pythonapi, \"Py_Version\")\n" ">>> print(hex(version.value))\n" "0x30c00a0" #: ../../library/ctypes.rst:1115 msgid "" "An extended example which also demonstrates the use of pointers accesses the" " :c:data:`PyImport_FrozenModules` pointer exported by Python." msgstr "" "一个扩展例子, 同时也展示了使用指针访问 Python 导出的 :c:data:`PyImport_FrozenModules` 指针对象。" #: ../../library/ctypes.rst:1118 msgid "Quoting the docs for that value:" msgstr "对文档中这个值的解释说明" #: ../../library/ctypes.rst:1120 msgid "" "This pointer is initialized to point to an array of :c:struct:`_frozen` " "records, terminated by one whose members are all ``NULL`` 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." msgstr "" "该指针被初始化为指向一个 :c:struct:`_frozen` 记录的数组,以一个所有成员均为 ``NULL`` 或零的记录表示结束。 " "当一个冻结模块被导入时,它将在此表中被搜索。 第三方代码可以利用此方式来提供动态创建的冻结模块集。" #: ../../library/ctypes.rst:1125 msgid "" "So manipulating this pointer could even prove useful. To restrict the " "example size, we show only how this table can be read with :mod:`ctypes`::" msgstr "这足以证明修改这个指针是很有用的。为了让实例大小不至于太长,这里只展示如何使用 :mod:`ctypes` 读取这个表::" #: ../../library/ctypes.rst:1128 msgid "" ">>> from ctypes import *\n" ">>>\n" ">>> class struct_frozen(Structure):\n" "... _fields_ = [(\"name\", c_char_p),\n" "... (\"code\", POINTER(c_ubyte)),\n" "... (\"size\", c_int),\n" "... (\"get_code\", POINTER(c_ubyte)), # Function pointer\n" "... ]\n" "...\n" ">>>" msgstr "" ">>> from ctypes import *\n" ">>>\n" ">>> class struct_frozen(Structure):\n" "... _fields_ = [(\"name\", c_char_p),\n" "... (\"code\", POINTER(c_ubyte)),\n" "... (\"size\", c_int),\n" "... (\"get_code\", POINTER(c_ubyte)), # 函数指针\n" "... ]\n" "...\n" ">>>" #: ../../library/ctypes.rst:1139 msgid "" "We have defined the :c:struct:`_frozen` data type, so we can get the pointer" " to the table::" msgstr "我们定义了 :c:struct:`_frozen` 数据类型,所以我们可以获取表的指针::" #: ../../library/ctypes.rst:1142 msgid "" ">>> FrozenTable = POINTER(struct_frozen)\n" ">>> table = FrozenTable.in_dll(pythonapi, \"_PyImport_FrozenBootstrap\")\n" ">>>" msgstr "" ">>> FrozenTable = POINTER(struct_frozen)\n" ">>> table = FrozenTable.in_dll(pythonapi, \"_PyImport_FrozenBootstrap\")\n" ">>>" #: ../../library/ctypes.rst:1146 msgid "" "Since ``table`` is a ``pointer`` to the array of ``struct_frozen`` records, " "we 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 ``NULL`` entry::" msgstr "" "由于 ``table`` 是指向 ``struct_frozen`` 数组的 ``指针`` " ",我们可以遍历它,只不过需要自己判断循环是否结束,因为指针本身并不包含长度。它早晚会因为访问到野指针或者什么的把自己搞崩溃,所以我们最好在遇到 " "``NULL`` 后就让它退出循环::" #: ../../library/ctypes.rst:1152 msgid "" ">>> for item in table:\n" "... if item.name is None:\n" "... break\n" "... print(item.name.decode(\"ascii\"), item.size)\n" "...\n" "_frozen_importlib 31764\n" "_frozen_importlib_external 41499\n" "zipimport 12345\n" ">>>" msgstr "" ">>> for item in table:\n" "... if item.name is None:\n" "... break\n" "... print(item.name.decode(\"ascii\"), item.size)\n" "...\n" "_frozen_importlib 31764\n" "_frozen_importlib_external 41499\n" "zipimport 12345\n" ">>>" #: ../../library/ctypes.rst:1162 msgid "" "The fact that standard Python has a frozen module and a frozen package " "(indicated by the negative ``size`` member) is not well known, it is only " "used for testing. Try it out with ``import __hello__`` for example." msgstr "" "Python 的冻结模块和冻结包(由负 ``size`` 成员表示)并不是广为人知的事情,它们仅仅用于实验。例如,可以使用 ``import " "__hello__`` 尝试一下这个功能。" #: ../../library/ctypes.rst:1170 msgid "Surprises" msgstr "意外" #: ../../library/ctypes.rst:1172 msgid "" "There are some edges in :mod:`ctypes` where you might expect something other" " than what actually happens." msgstr ":mod:`ctypes` 也有自己的边界,有时候会发生一些意想不到的事情。" #: ../../library/ctypes.rst:1175 msgid "Consider the following example::" msgstr "比如下面的例子::" #: ../../library/ctypes.rst:1177 msgid "" ">>> from ctypes import *\n" ">>> class POINT(Structure):\n" "... _fields_ = (\"x\", c_int), (\"y\", c_int)\n" "...\n" ">>> class RECT(Structure):\n" "... _fields_ = (\"a\", POINT), (\"b\", POINT)\n" "...\n" ">>> p1 = POINT(1, 2)\n" ">>> p2 = POINT(3, 4)\n" ">>> rc = RECT(p1, p2)\n" ">>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)\n" "1 2 3 4\n" ">>> # now swap the two points\n" ">>> rc.a, rc.b = rc.b, rc.a\n" ">>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)\n" "3 4 3 4\n" ">>>" msgstr "" ">>> from ctypes import *\n" ">>> class POINT(Structure):\n" "... _fields_ = (\"x\", c_int), (\"y\", c_int)\n" "...\n" ">>> class RECT(Structure):\n" "... _fields_ = (\"a\", POINT), (\"b\", POINT)\n" "...\n" ">>> p1 = POINT(1, 2)\n" ">>> p2 = POINT(3, 4)\n" ">>> rc = RECT(p1, p2)\n" ">>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)\n" "1 2 3 4\n" ">>> # 现在交换这两个\n" ">>> rc.a, rc.b = rc.b, rc.a\n" ">>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)\n" "3 4 3 4\n" ">>>" #: ../../library/ctypes.rst:1195 msgid "" "Hm. We certainly expected the last statement to print ``3 4 1 2``. What " "happened? Here are the steps of the ``rc.a, rc.b = rc.b, rc.a`` line above::" msgstr "" "嗯。我们预想应该打印 ``3 4 1 2`` 。但是为什么呢? 这是 ``rc.a, rc.b = rc.b, rc.a`` 这行代码展开后的步骤::" #: ../../library/ctypes.rst:1198 msgid "" ">>> temp0, temp1 = rc.b, rc.a\n" ">>> rc.a = temp0\n" ">>> rc.b = temp1\n" ">>>" msgstr "" ">>> temp0, temp1 = rc.b, rc.a\n" ">>> rc.a = temp0\n" ">>> rc.b = temp1\n" ">>>" #: ../../library/ctypes.rst:1203 msgid "" "Note that ``temp0`` and ``temp1`` are objects still using the internal " "buffer of the ``rc`` object above. So executing ``rc.a = temp0`` copies the " "buffer contents of ``temp0`` into ``rc`` 's buffer. This, in turn, changes " "the contents of ``temp1``. So, the last assignment ``rc.b = temp1``, doesn't" " have the expected effect." msgstr "" "注意 ``temp0`` 和 ``temp1`` 对象始终引用了对象 ``rc`` 的内容。然后执行 ``rc.a = temp0`` 会把 " "``temp0`` 的内容拷贝到 ``rc`` 的空间。这也改变了 ``temp1`` 的内容。最终导致赋值语句 ``rc.b = temp1`` " "没有产生预想的效果。" #: ../../library/ctypes.rst:1209 msgid "" "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." msgstr "记住,访问被包含在结构体、联合、数组中的对象并不会将其 *复制* 出来,而是得到了一个代理对象,它是对根对象的内部内容的一层包装。" #: ../../library/ctypes.rst:1213 msgid "" "Another example that may behave differently from what one would expect is " "this::" msgstr "下面是另一个可能和预期有偏差的例子::" #: ../../library/ctypes.rst:1215 msgid "" ">>> s = c_char_p()\n" ">>> s.value = b\"abc def ghi\"\n" ">>> s.value\n" "b'abc def ghi'\n" ">>> s.value is s.value\n" "False\n" ">>>" msgstr "" ">>> s = c_char_p()\n" ">>> s.value = b\"abc def ghi\"\n" ">>> s.value\n" "b'abc def ghi'\n" ">>> s.value is s.value\n" "False\n" ">>>" #: ../../library/ctypes.rst:1225 msgid "" "Objects instantiated from :class:`c_char_p` can only have their value set to" " bytes or integers." msgstr "使用 :class:`c_char_p`  实例化的对象只能将其值设置为 bytes 或者整数。" #: ../../library/ctypes.rst:1228 msgid "" "Why is it printing ``False``? ctypes instances are objects containing a " "memory block plus some :term:`descriptor`\\s accessing the contents of the " "memory. Storing a Python object in the memory block does not store the " "object itself, instead the ``contents`` of the object is stored. Accessing " "the contents again constructs a new Python object each time!" msgstr "" "为什么这里打印了 ``False`` ? ctypes 实例是一些内存块加上一些用于访问这些内存块的 :term:`descriptor` 组成。将 " "Python 对象存储在内存块并不会存储对象本身,而是存储了对象的 ``内容`` 。每次访问对象的内容都会构造一个新的 Python 对象。" #: ../../library/ctypes.rst:1238 msgid "Variable-sized data types" msgstr "变长数据类型" #: ../../library/ctypes.rst:1240 msgid "" ":mod:`ctypes` provides some support for variable-sized arrays and " "structures." msgstr ":mod:`ctypes` 对变长数组和结构体提供了一些支持 。" #: ../../library/ctypes.rst:1242 msgid "" "The :func:`resize` function can be used to resize the memory buffer of an " "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 :exc:`ValueError` is raised if this is tried::" msgstr "" " :func:`resize` 函数可以用于改变已有的 ctypes " "对象内存缓冲区大小。此函数第一个参数是ctypes对象,第二个参数是要求调整后的大小,单位是字节。不能使存储块小于对象的原有大小,否则抛出 " ":exc:`ValueError` 异常。" #: ../../library/ctypes.rst:1248 msgid "" ">>> short_array = (c_short * 4)()\n" ">>> print(sizeof(short_array))\n" "8\n" ">>> resize(short_array, 4)\n" "Traceback (most recent call last):\n" " ...\n" "ValueError: minimum size is 8\n" ">>> resize(short_array, 32)\n" ">>> sizeof(short_array)\n" "32\n" ">>> sizeof(type(short_array))\n" "8\n" ">>>" msgstr "" ">>> short_array = (c_short * 4)()\n" ">>> print(sizeof(short_array))\n" "8\n" ">>> resize(short_array, 4)\n" "Traceback (most recent call last):\n" " ...\n" "ValueError: minimum size is 8\n" ">>> resize(short_array, 32)\n" ">>> sizeof(short_array)\n" "32\n" ">>> sizeof(type(short_array))\n" "8\n" ">>>" #: ../../library/ctypes.rst:1262 msgid "" "This is nice and fine, but how would one access the additional elements " "contained in this array? Since the type still only knows about 4 elements, " "we get errors accessing other elements::" msgstr "这非常好,但是要怎么访问数组中额外的元素呢?因为数组类型已经定义包含4个元素,导致我们访问新增元素时会产生以下错误::" #: ../../library/ctypes.rst:1266 msgid "" ">>> short_array[:]\n" "[0, 0, 0, 0]\n" ">>> short_array[7]\n" "Traceback (most recent call last):\n" " ...\n" "IndexError: invalid index\n" ">>>" msgstr "" ">>> short_array[:]\n" "[0, 0, 0, 0]\n" ">>> short_array[7]\n" "Traceback (most recent call last):\n" " ...\n" "IndexError: invalid index\n" ">>>" #: ../../library/ctypes.rst:1274 msgid "" "Another way to use variable-sized data types with :mod:`ctypes` is to use " "the dynamic nature of Python, and (re-)define the data type after the " "required size is already known, on a case by case basis." msgstr "" "使用 :mod:`ctypes` 访问变长数据类型的一个可行方法是利用 Python " "的动态特性,根据具体情况,在知道这个数据的大小后,(重新)指定这个数据的类型。" #: ../../library/ctypes.rst:1282 msgid "ctypes reference" msgstr "ctypes 参考手册" #: ../../library/ctypes.rst:1288 msgid "Finding shared libraries" msgstr "寻找动态链接库" #: ../../library/ctypes.rst:1290 msgid "" "When programming in a compiled language, shared libraries are accessed when " "compiling/linking a program, and when the program is run." msgstr "在编译型语言中,动态链接库会在编译、链接或者程序运行时访问。" #: ../../library/ctypes.rst:1293 msgid "" "The purpose of the :func:`~ctypes.util.find_library` function is to locate a" " library in a way 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." msgstr "" ":func:`~ctypes.util.find_library` " "函数的目的是以类似于编译器或运行时加载器的方式来定位库(在有多个共享库版本的平台上应当加载最新的版本),而 ctypes " "库加载器的行为类似于程序已经运行时直接调用运行时加载器。" #: ../../library/ctypes.rst:1299 msgid "" "The :mod:`!ctypes.util` module provides a function which can help to " "determine the library to load." msgstr ":mod:`!ctypes.util` 模块提供了一个函数,可以帮助确定要加载的库。" #: ../../library/ctypes.rst:1307 msgid "" "Try to find a library and return a pathname. *name* is the library name " "without any prefix like *lib*, suffix like ``.so``, ``.dylib`` or version " "number (this is the form used for the posix linker option :option:`!-l`). " "If no library can be found, returns ``None``." msgstr "" "尝试寻找一个库然后返回其路径名, *name* 是库名称, 且去除了 *lib* 等前缀和 ``.so`` 、 ``.dylib`` " "、版本号等后缀(这是 posix 连接器 :option:`!-l` 选项使用的格式)。如果没有找到对应的库,则返回 ``None`` 。" #: ../../library/ctypes.rst:1312 ../../library/ctypes.rst:1997 msgid "The exact functionality is system dependent." msgstr "确切的功能取决于系统。" #: ../../library/ctypes.rst:1314 msgid "" "On Linux, :func:`~ctypes.util.find_library` tries to run external programs " "(``/sbin/ldconfig``, ``gcc``, ``objdump`` and ``ld``) to find the library " "file. It returns the filename of the library file." msgstr "" "在 Linux 中,:func:`~ctypes.util.find_library` 会尝试运行外部程序 (``/sbin/ldconfig``, " "``gcc``, ``objdump`` 和 ``ld``) 来查找库文件。 它会返回库文件的文件名。" #: ../../library/ctypes.rst:1318 msgid "" "On Linux, the value of the environment variable ``LD_LIBRARY_PATH`` is used " "when searching for libraries, if a library cannot be found by any other " "means." msgstr "在Linux 上,如果其他方式找不到的话,会使用环境变量 ``LD_LIBRARY_PATH`` 搜索动态链接库。" #: ../../library/ctypes.rst:1322 msgid "Here are some examples::" msgstr "这是一些例子::" #: ../../library/ctypes.rst:1324 msgid "" ">>> from ctypes.util import find_library\n" ">>> find_library(\"m\")\n" "'libm.so.6'\n" ">>> find_library(\"c\")\n" "'libc.so.6'\n" ">>> find_library(\"bz2\")\n" "'libbz2.so.1.0'\n" ">>>" msgstr "" ">>> from ctypes.util import find_library\n" ">>> find_library(\"m\")\n" "'libm.so.6'\n" ">>> find_library(\"c\")\n" "'libc.so.6'\n" ">>> find_library(\"bz2\")\n" "'libbz2.so.1.0'\n" ">>>" #: ../../library/ctypes.rst:1333 msgid "" "On macOS, :func:`~ctypes.util.find_library` tries several predefined naming " "schemes and paths to locate the library, and returns a full pathname if " "successful::" msgstr "" "在 macOS 上,:func:`~ctypes.util.find_library` " "会尝试几种预定义的命名方案和路径来查找库,并在成功时返回完整路径名::" #: ../../library/ctypes.rst:1336 msgid "" ">>> from ctypes.util import find_library\n" ">>> find_library(\"c\")\n" "'/usr/lib/libc.dylib'\n" ">>> find_library(\"m\")\n" "'/usr/lib/libm.dylib'\n" ">>> find_library(\"bz2\")\n" "'/usr/lib/libbz2.dylib'\n" ">>> find_library(\"AGL\")\n" "'/System/Library/Frameworks/AGL.framework/AGL'\n" ">>>" msgstr "" ">>> from ctypes.util import find_library\n" ">>> find_library(\"c\")\n" "'/usr/lib/libc.dylib'\n" ">>> find_library(\"m\")\n" "'/usr/lib/libm.dylib'\n" ">>> find_library(\"bz2\")\n" "'/usr/lib/libbz2.dylib'\n" ">>> find_library(\"AGL\")\n" "'/System/Library/Frameworks/AGL.framework/AGL'\n" ">>>" #: ../../library/ctypes.rst:1347 msgid "" "On Windows, :func:`~ctypes.util.find_library` searches along the system " "search path, and returns the full pathname, but since there is no predefined" " naming scheme a call like ``find_library(\"c\")`` will fail and return " "``None``." msgstr "" "在 Windows 中,:func:`~ctypes.util.find_library` " "会沿着系统搜索路径进行搜索,并返回完整的路径名称,但由于没有预定义的命名方案因此像 ``find_library(\"c\")`` " "这样的调用会失败并返回 ``None``。" #: ../../library/ctypes.rst:1351 msgid "" "If wrapping a shared library with :mod:`ctypes`, it *may* be better to " "determine the shared library name at development time, and hardcode that " "into the wrapper module instead of using :func:`~ctypes.util.find_library` " "to locate the library at runtime." msgstr "" "如果使用 :mod:`ctypes` 包装一个共享库,则更好的做法 *可能* 是开发时就确定好共享库的名称,并将其硬编码到包装模块中而不是在运行时使用 " ":func:`~ctypes.util.find_library` 来定位库。" #: ../../library/ctypes.rst:1359 msgid "Loading shared libraries" msgstr "加载动态链接库" #: ../../library/ctypes.rst:1361 msgid "" "There are several ways to load shared libraries into the Python process. " "One way is to instantiate one of the following classes:" msgstr "有很多方式可以将动态链接库加载到 Python 进程。其中之一是实例化以下类的其中一个::" #: ../../library/ctypes.rst:1367 msgid "" "Instances of this class represent loaded shared libraries. Functions in " "these libraries use the standard C calling convention, and are assumed to " "return :c:expr:`int`." msgstr "该类的实例代表已加载的共享库。 这些库中的函数使用标准的 C 调用约定,并被预期会返回 :c:expr:`int`。" #: ../../library/ctypes.rst:1371 msgid "" "On Windows creating a :class:`CDLL` instance may fail even if the DLL name " "exists. When a dependent DLL of the loaded DLL is not found, a " ":exc:`OSError` error is raised with the message *\"[WinError 126] The " "specified module could not be found\".* 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." msgstr "" "在 Windows 上创建 :class:`CDLL` 实例可能会失败,即使 DLL 名称确实存在。 当某个被加载 DLL 所依赖的 DLL " "未找到时,将引发 :exc:`OSError` 错误并附带消息 *\"[WinError 126] The specified module could" " not be found\".* 此错误消息不包含缺失 DLL 的名称,因为 Windows API 并不会返回此类信息,这使得此错误难以诊断。 " "要解决此错误并确定是哪一个 DLL 未找到,你需要找出所依赖的 DLL 列表并使用 Windows 调试与跟踪工具确定是哪一个未找到。" #: ../../library/ctypes.rst:1383 ../../library/ctypes.rst:1408 #: ../../library/ctypes.rst:1421 ../../library/ctypes.rst:1439 msgid "The *name* parameter can now be a :term:`path-like object`." msgstr "现在 *name* 形参可以是一个 :term:`path-like object`。" #: ../../library/ctypes.rst:1387 msgid "" "`Microsoft DUMPBIN tool " "`_ -- A tool to " "find DLL dependents." msgstr "" "`Microsoft DUMPBIN 工具 " "`_ -- 一个用于查找 DLL " "依赖的工具。" #: ../../library/ctypes.rst:1393 msgid "" "Instances of this class represent loaded shared libraries, functions in " "these libraries use the ``stdcall`` calling convention, and are assumed to " "return the windows specific :class:`HRESULT` code. :class:`HRESULT` values " "contain information specifying whether the function call failed or " "succeeded, together with additional error code. If the return value signals" " a failure, an :class:`OSError` is automatically raised." msgstr "" "这个类的实例代表已加载的共享库,这些库中的函数使用 ``stdcall`` 调用约定,并且预期返回 Windows 专属的 " ":class:`HRESULT` 代码。 :class:`HRESULT` 值包含指明函数调用是失败还是成功的信息,并带有额外的错误码。 " "如果返回值是提示失败,则会自动引发 :class:`OSError`。" #: ../../library/ctypes.rst:1400 ../../library/ctypes.rst:1417 #: ../../library/ctypes.rst:1561 ../../library/ctypes.rst:1569 #: ../../library/ctypes.rst:1746 ../../library/ctypes.rst:1977 #: ../../library/ctypes.rst:1986 ../../library/ctypes.rst:2011 #: ../../library/ctypes.rst:2020 ../../library/ctypes.rst:2029 #: ../../library/ctypes.rst:2044 ../../library/ctypes.rst:2101 #: ../../library/ctypes.rst:2129 ../../library/ctypes.rst:2473 msgid "Availability" msgstr "Availability" #: ../../library/ctypes.rst:1402 msgid "" ":exc:`WindowsError` used to be raised, which is now an alias of " ":exc:`OSError`." msgstr "过去会引发 :exc:`WindowsError`,现在它是 :exc:`OSError` 的别名。" #: ../../library/ctypes.rst:1413 msgid "" "Instances of this class represent loaded shared libraries, functions in " "these libraries use the ``stdcall`` calling convention, and are assumed to " "return :c:expr:`int` by default." msgstr "这个类的实例代表已加载的共享库,这些库中的函数使用 ``stdcall`` 调用约定,并且默认预期返回 :c:expr:`int`。" #: ../../library/ctypes.rst:1424 msgid "" "The Python :term:`global interpreter lock` is released before calling any " "function exported by these libraries, and reacquired afterwards." msgstr "调用动态库导出的函数之前,Python会释放 :term:`global interpreter lock` ,并在调用后重新获取。" #: ../../library/ctypes.rst:1430 msgid "" "Instances of this class behave like :class:`CDLL` instances, except that the" " Python GIL is *not* released during the function call, and after the " "function execution the Python error flag is checked. If the error flag is " "set, a Python exception is raised." msgstr "" "这个类实例的行为与 :class:`CDLL` 类似,只不过 *不会* 在调用函数的时候释放 GIL 锁,且调用结束后会检查 Python 错误码。 " "如果错误码被设置,会抛出一个 Python 异常。" #: ../../library/ctypes.rst:1435 msgid "Thus, this is only useful to call Python C api functions directly." msgstr "所以,它只在直接调用 Python C 接口函数的时候有用。" #: ../../library/ctypes.rst:1441 msgid "" "All these classes can be instantiated by calling them with at least one " "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 " "``handle`` named parameter, otherwise the underlying platforms " ":c:func:`!dlopen` or :c:func:`!LoadLibrary` function is used to load the " "library into the process, and to get a handle to it." msgstr "" "所有这些类都可以传入至少一个参数作为共享库的路径名来实例化。 如果你有一个已经加载的共享库的句柄,可以将其作为``handle`` " "参数传递,否则,底层平台的 :c:func:`!dlopen` 或 :c:func:`!LoadLibrary` " "函数将用于将库加载到进程中,并获取其句柄。" #: ../../library/ctypes.rst:1448 msgid "" "The *mode* parameter can be used to specify how the library is loaded. For " "details, consult the :manpage:`dlopen(3)` manpage. On Windows, *mode* is " "ignored. On posix systems, RTLD_NOW is always added, and is not " "configurable." msgstr "" "*mode* 可以指定库加载方式。详情请参见 :manpage:`dlopen(3)` 手册页。 在 Windows 上, 会忽略 *mode* ,在" " posix 系统上, 总是会加上 RTLD_NOW ,且无法配置。" #: ../../library/ctypes.rst:1453 msgid "" "The *use_errno* parameter, when set to true, enables a ctypes mechanism that" " allows accessing the system :data:`errno` error number in a safe way. " ":mod:`ctypes` maintains a thread-local copy of the systems :data:`errno` " "variable; if you call foreign functions created with ``use_errno=True`` then" " the :data:`errno` value before the function call is swapped with the ctypes" " private copy, the same happens immediately after the function call." msgstr "" "对于 *use_errno* 参数,如果设为真,则 ctypes 会启用一种安全访问系统 :data:`errno` 的机制。 " ":mod:`ctypes` 维护有系统 :data:`errno` 的一个线程局部副本;如果调用传入了 ``use_errno=True`` " "的外部函数,函数调用前 :data:`errno` 的值将与 ctypes 的私有副本交换,函数调用后也进行同样的交换。" #: ../../library/ctypes.rst:1460 msgid "" "The function :func:`ctypes.get_errno` returns the value of the ctypes " "private copy, and the function :func:`ctypes.set_errno` changes the ctypes " "private copy to a new value and returns the former value." msgstr "" " :func:`ctypes.get_errno` 返回 ctypes 自己维护的那份拷贝的值, :func:`ctypes.set_errno` " "函数可以修改它并返回之前的值。" #: ../../library/ctypes.rst:1464 msgid "" "The *use_last_error* parameter, when set to true, enables the same mechanism" " for the Windows error code which is managed by the :func:`GetLastError` and" " :func:`!SetLastError` Windows API functions; :func:`ctypes.get_last_error` " "and :func:`ctypes.set_last_error` are used to request and change the ctypes " "private copy of the windows error code." msgstr "" "当 *use_last_error* 形参设为真值时,为 Windows 错误代码也启用与由 :func:`GetLastError` 和 " ":func:`!SetLastError` Windows API 函数管理相同的机制;:func:`ctypes.get_last_error` 和 " ":func:`ctypes.set_last_error` 会被用于请求和更改 Windows 错误代码的 ctypes 私有副本。" #: ../../library/ctypes.rst:1470 msgid "" "The *winmode* parameter is used on Windows to specify how the library is " "loaded (since *mode* is ignored). It takes any value that is valid for the " "Win32 API ``LoadLibraryEx`` flags parameter. When omitted, the default is to" " use the flags that result in the most secure DLL load, which avoids 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." msgstr "" "*winmode* 形参用于在 Windows 上指定库的加载方式(因为 *mode* 会被忽略)。 它接受任何对 Win32 API " "``LoadLibraryEx`` 旗标形参来说合法的值。 当被省略时,默认使用表示最安全的 DLL 加载的旗标,这将避免 DLL 劫持等问题。 传入 " "DLL 的完整路径是确保正确加载库及其依赖的最安全的方式。" #: ../../library/ctypes.rst:1477 msgid "Added *winmode* parameter." msgstr "增加了 *winmode* 参数。" #: ../../library/ctypes.rst:1484 msgid "" "Flag to use as *mode* parameter. On platforms where this flag is not " "available, it is defined as the integer zero." msgstr "用于 *mode* 参数的标识值。在此标识不可用的系统上,它被定义为整数0。" #: ../../library/ctypes.rst:1491 msgid "" "Flag to use as *mode* parameter. On platforms where this is not available, " "it is the same as *RTLD_GLOBAL*." msgstr " 用于 *mode* 参数的标识值。在此标识不可用的系统上,它和 *RTLD_GLOBAL* 一样。" #: ../../library/ctypes.rst:1498 msgid "" "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*." msgstr "加载动态链接库的默认模式。在 OSX 10.3 上,它是 *RTLD_GLOBAL* ,其余系统上是 *RTLD_LOCAL* 。" #: ../../library/ctypes.rst:1501 msgid "" "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::" msgstr "" "这些类的实例没有共用方法。动态链接库的导出函数可以通过属性或者索引的方式访问。注意,通过属性的方式访问会缓存这个函数,因而每次访问它时返回的都是同一个对象。另一方面,通过索引访问,每次都会返回一个新的对象::" #: ../../library/ctypes.rst:1507 msgid "" ">>> from ctypes import CDLL\n" ">>> libc = CDLL(\"libc.so.6\") # On Linux\n" ">>> libc.time == libc.time\n" "True\n" ">>> libc['time'] == libc['time']\n" "False" msgstr "" ">>> from ctypes import CDLL\n" ">>> libc = CDLL(\"libc.so.6\") # 在 Linux\n" ">>> libc.time == libc.time\n" "True\n" ">>> libc['time'] == libc['time']\n" "False" #: ../../library/ctypes.rst:1514 msgid "" "The following public attributes are available, their name starts with an " "underscore to not clash with exported function names:" msgstr "还有下面这些属性可用,他们的名称以下划线开头,以避免和导出函数重名:" #: ../../library/ctypes.rst:1520 msgid "The system handle used to access the library." msgstr "用于访问库的系统句柄。" #: ../../library/ctypes.rst:1525 msgid "The name of the library passed in the constructor." msgstr "传入构造函数的库名称。" #: ../../library/ctypes.rst:1527 msgid "" "Shared libraries can also be loaded by using one of the prefabricated " "objects, which are instances of the :class:`LibraryLoader` class, either by " "calling the :meth:`~LibraryLoader.LoadLibrary` method, or by retrieving the " "library as attribute of the loader instance." msgstr "" "共享库也可以通过使用一个预制对象来加载,这种对象是 :class:`LibraryLoader` 类的实例,具体做法是调用 " ":meth:`~LibraryLoader.LoadLibrary` 方法,或是将库作为加载器实例的属性来提取。" #: ../../library/ctypes.rst:1535 msgid "" "Class which loads shared libraries. *dlltype* should be one of the " ":class:`CDLL`, :class:`PyDLL`, :class:`WinDLL`, or :class:`OleDLL` types." msgstr "" "加载共享库的类。 *dlltype* 应当为 :class:`CDLL`, :class:`PyDLL`, :class:`WinDLL` 或 " ":class:`OleDLL` 类型之一。" #: ../../library/ctypes.rst:1538 msgid "" ":meth:`!__getattr__` 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." msgstr "" ":meth:`!__getattr__` 具有特殊的行为:它允许通过一个作为库加载器实例的属性访问共享库来加载它。 " "访问结果会被缓存,因此每次重复的属性访问都会返回相同的库。" #: ../../library/ctypes.rst:1544 msgid "" "Load a shared library into the process and return it. This method always " "returns a new instance of the library." msgstr "加载一个共享库到进程中并将其返回。 此方法总是返回一个新的库实例。" #: ../../library/ctypes.rst:1548 msgid "These prefabricated library loaders are available:" msgstr "可用的预制库加载器有如下这些:" #: ../../library/ctypes.rst:1553 msgid "Creates :class:`CDLL` instances." msgstr "创建 :class:`CDLL` 实例。" #: ../../library/ctypes.rst:1559 msgid "Creates :class:`WinDLL` instances." msgstr "创建 :class:`WinDLL` 实例。" #: ../../library/ctypes.rst:1567 msgid "Creates :class:`OleDLL` instances." msgstr "创建 :class:`OleDLL` 实例。" #: ../../library/ctypes.rst:1575 msgid "Creates :class:`PyDLL` instances." msgstr "创建 :class:`PyDLL` 实例。" #: ../../library/ctypes.rst:1578 msgid "" "For accessing the C Python api directly, a ready-to-use Python shared " "library object is available:" msgstr "要直接访问 C Python api,可以使用一个现成的 Python 共享库对象:" #: ../../library/ctypes.rst:1584 msgid "" "An instance of :class:`PyDLL` that exposes Python C API functions as " "attributes. Note that all these functions are assumed to return C " ":c:expr:`int`, which is of course not always the truth, so you have to " "assign the correct :attr:`!restype` attribute to use these functions." msgstr "" "一个将 Python C API 函数作为属性公开出来的 :class:`PyDLL` 实例。 请注意所有这些函数都应返回 C " ":c:expr:`int`,当然也并非总是如此,因此您必须分配正确的 :attr:`!restype` 属性才能使用这些函数。" #: ../../library/ctypes.rst:1589 ../../library/ctypes.rst:1591 msgid "" "Loading a library through any of these objects raises an :ref:`auditing " "event ` ``ctypes.dlopen`` with string argument ``name``, the name " "used to load the library." msgstr "" "通过这些对象中的任何一个加载库都将引发一个 :ref:`审计事件 ` ``ctypes.dlopen`` 并附带字符串参数 " "``name``,即用于加载库的名称。" #: ../../library/ctypes.rst:1595 ../../library/ctypes.rst:1597 msgid "" "Accessing a function on a loaded library raises an auditing event " "``ctypes.dlsym`` with arguments ``library`` (the library object) and " "``name`` (the symbol's name as a string or integer)." msgstr "" "在加载的库上访问一个函数将引发一个审计事件 ``ctypes.dlsym`` 并附带参数 ``library`` (库对象) 和 ``name`` " "(以字符串或整数表示的符号名称)." #: ../../library/ctypes.rst:1601 ../../library/ctypes.rst:1603 msgid "" "In cases when only the library handle is available rather than the object, " "accessing a function raises an auditing event ``ctypes.dlsym/handle`` with " "arguments ``handle`` (the raw library handle) and ``name``." msgstr "" "在只有库句柄而非对象可用的情况下,访问函数会引发一个审计事件 ``ctypes.dlsym/handle`` 并附带参数 ``handle`` " "(原始库句柄) 和 ``name``。" #: ../../library/ctypes.rst:1610 msgid "Foreign functions" msgstr "外部函数" #: ../../library/ctypes.rst:1612 msgid "" "As explained in the previous section, foreign functions can be accessed as " "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." msgstr "" "正如前一节的说明,外部函数可作为已加载共享库的属性来访问。 用此方式创建的函数对象默认接受任意数量的参数,接受任意 ctypes " "数据实例作为参数,并且返回库加载器所指定的默认结果类型。" #: ../../library/ctypes.rst:1617 msgid "" "They are instances of a private local class :class:`!_FuncPtr` (not exposed " "in :mod:`!ctypes`) which inherits from the private :class:`_CFuncPtr` class:" msgstr "" "它们是私有局部类 :class:`!_FuncPtr` 的实例(未在 :mod:`!ctypes` 中暴露),该类继承自私有的 " ":class:`_CFuncPtr` 类:" #: ../../library/ctypes.rst:1620 msgid "" ">>> import ctypes\n" ">>> lib = ctypes.CDLL(None)\n" ">>> issubclass(lib._FuncPtr, ctypes._CFuncPtr)\n" "True\n" ">>> lib._FuncPtr is ctypes._CFuncPtr\n" "False" msgstr "" ">>> import ctypes\n" ">>> lib = ctypes.CDLL(None)\n" ">>> issubclass(lib._FuncPtr, ctypes._CFuncPtr)\n" "True\n" ">>> lib._FuncPtr is ctypes._CFuncPtr\n" "False" #: ../../library/ctypes.rst:1631 msgid "Base class for C callable foreign functions." msgstr "C 可调用外部函数的基类。" #: ../../library/ctypes.rst:1633 msgid "" "Instances of foreign functions are also C compatible data types; they " "represent C function pointers." msgstr "外部函数的实例也是兼容 C 的数据类型;它们代表 C 函数指针。" #: ../../library/ctypes.rst:1636 msgid "" "This behavior can be customized by assigning to special attributes of the " "foreign function object." msgstr "此行为可通过对外部函数对象的特殊属性赋值来自定义。" #: ../../library/ctypes.rst:1641 msgid "" "Assign a ctypes type to specify the result type of the foreign function. Use" " ``None`` for :c:expr:`void`, a function not returning anything." msgstr "" "分配一个 ctypes 类型来指定外部函数的结果类型。 使用 ``None`` 来表示 :c:expr:`void`,即不返回任何结果的函数。" #: ../../library/ctypes.rst:1644 msgid "" "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 :c:expr:`int`, 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 :attr:`!restype` and assign a " "callable to the :attr:`errcheck` attribute." msgstr "" "赋值为一个非 ctypes 类型的可调用 Python 对象也是可以的,在这种情况下函数应返回 C " ":c:expr:`int`,并且该可调用对象将附带此整数被调用,以允许进一步的处理或错误检查。 " "这种用法已被弃用,为了更灵活地进行后续处理或错误检查请使用 ctypes 数据类型作为 :attr:`!restype` 并将 " ":attr:`errcheck` 属性赋值为一个可调用对象。" #: ../../library/ctypes.rst:1653 msgid "" "Assign a tuple of ctypes types to specify the argument types that the " "function accepts. Functions using the ``stdcall`` calling convention can " "only be called with the same number of arguments as the length of this " "tuple; functions using the C calling convention accept additional, " "unspecified arguments as well." msgstr "" "赋值为一个 ctypes 类型的元组来指定函数所接受的参数类型。 使用 ``stdcall`` " "调用规范的函数只能附带与此元组长度相同数量的参数进行调用;使用 C 调用规范的函数还可接受额外的未指明参数。" #: ../../library/ctypes.rst:1659 msgid "" "When a foreign function is called, each actual argument is passed to the " ":meth:`~_CData.from_param` class method of the items in the :attr:`argtypes`" " tuple, this method allows adapting the actual argument to an object that " "the foreign function accepts. For example, a :class:`c_char_p` item in the " ":attr:`argtypes` tuple will convert a string passed as argument into a bytes" " object using ctypes conversion rules." msgstr "" "当调用外部函数时,每个实际参数都会被传给 :attr:`argtypes` 元组中条目的 :meth:`~_CData.from_param` " "类方法,该方法允许将实际参数适配为此外部函数所接受的对象。 例如,:attr:`argtypes` 元组中的 :class:`c_char_p` " "条目将使用 ctypes 转换规则把作为参数传入的字符串转换为字节串对象。" #: ../../library/ctypes.rst:1666 msgid "" "New: It is now possible to put items in argtypes which are not ctypes types," " but each item must have a :meth:`~_CData.from_param` method which returns a" " value usable as argument (integer, string, ctypes instance). This allows " "defining adapters that can adapt custom objects as function parameters." msgstr "" "新特性:现在可以在 argtypes 中放入非 ctypes 类型的条目,但每个条目必须具有 :meth:`~_CData.from_param` " "方法用于返回一个可作为参数的值(整数、字符串、ctypes 实例)。 这样就允许定义可将将自定义对象适配为函数参数的适配器。" #: ../../library/ctypes.rst:1673 msgid "" "Assign a Python function or another callable to this attribute. The callable" " will be called with three or more arguments:" msgstr "将一个 Python 函数或其他可调用对象赋值给此属性。 该可调用对象将附带三个及以上的参数被调用。" #: ../../library/ctypes.rst:1680 msgid "" "*result* is what the foreign function returns, as specified by the " ":attr:`!restype` attribute." msgstr "*result* 是外部函数返回的结果,由 :attr:`!restype` 属性指明。" #: ../../library/ctypes.rst:1683 msgid "" "*func* is the foreign function object itself, this allows reusing the same " "callable object to check or post process the results of several functions." msgstr "*func* 是外部函数对象本身,这样就允许重新使用相同的可调用对象来对多个函数进行检查或后续处理。" #: ../../library/ctypes.rst:1687 msgid "" "*arguments* is a tuple containing the parameters originally passed to the " "function call, this allows specializing the behavior on the arguments used." msgstr "*arguments* 是一个包含最初传递给函数调用的形参的元组,这样就允许对所用参数的行为进行特别处理。" #: ../../library/ctypes.rst:1691 msgid "" "The object that this function returns will be returned from the foreign " "function call, but it can also check the result value and raise an exception" " if the foreign function call failed." msgstr "此函数所返回的对象将会由外部函数调用返回,但它还可以在外部函数调用失败时检查结果并引发异常。" #: ../../library/ctypes.rst:1698 msgid "" "This exception is raised when a foreign function call cannot convert one of " "the passed arguments." msgstr "此异常会在外部函数无法对某个传入参数执行转换时被引发。" #: ../../library/ctypes.rst:1702 ../../library/ctypes.rst:1704 msgid "" "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 " "``ctypes.set_exception`` with argument ``code`` will be raised, allowing an " "audit hook to replace the exception with its own." msgstr "" "在 Windows 上,当外部函数调用引发一个系统异常时(例如由于访问冲突),它将被捕获并被替换为适当的 Python 异常。 " "此外,还将引发一个审计事件 ``ctypes.set_exception`` 并附带参数 ``code``,以允许审计钩子将原异常替换为它自己的异常。" #: ../../library/ctypes.rst:1710 ../../library/ctypes.rst:1712 msgid "" "Some ways to invoke foreign function calls may raise an auditing event " "``ctypes.call_function`` with arguments ``function pointer`` and " "``arguments``." msgstr "" "某些发起外部函数调用的方式可能会引发一个审计事件 ``ctypes.call_function`` 并附带参数 ``function pointer``" " 和 ``arguments``。" #: ../../library/ctypes.rst:1718 msgid "Function prototypes" msgstr "函数原型" #: ../../library/ctypes.rst:1720 msgid "" "Foreign functions can also be created by instantiating function prototypes. " "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 " "``@wrapper`` syntax. See :ref:`ctypes-callback-functions` for examples." msgstr "" "外部函数也可通过实例化函数原型来创建。 函数原型类似于 C 中的函数原型;它们在不定义具体实现的情况下描述了一个函数(返回类型、参数类型、调用约定)。 " "工厂函数必须使用函数所需要的结果类型和参数类型来调用,并可被用作装饰器工厂函数,在此情况下可以通过 ``@wrapper`` 语法应用于函数。 请参阅 " ":ref:`ctypes-callback-functions` 了解有关示例。" #: ../../library/ctypes.rst:1731 msgid "" "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 " ":data:`errno` variable is exchanged with the real :data:`errno` value before" " and after the call; *use_last_error* does the same for the Windows error " "code." msgstr "" "返回的函数原型会创建使用标准 C 调用约定的函数。 该函数在调用过程中将释放 GIL。 如果 *use_errno* 设为真值,则在调用之前和之后系统 " ":data:`errno` 变量的 ctypes 私有副本会与真正的 :data:`errno` 值进行交换;*use_last_error* 会为 " "Windows 错误码执行同样的操作。" #: ../../library/ctypes.rst:1741 msgid "" "The returned function prototype creates functions that use the ``stdcall`` " "calling convention. The function will release the GIL during the call. " "*use_errno* and *use_last_error* have the same meaning as above." msgstr "" "返回的函数原型会创建使用 ``stdcall`` 调用约定的函数。 该函数在调用过程中将会释放 GIL。 *use_errno* 和 " "*use_last_error* 具有与上文相同的含义。" #: ../../library/ctypes.rst:1751 msgid "" "The returned function prototype creates functions that use the Python " "calling convention. The function will *not* release the GIL during the " "call." msgstr "返回的函数原型会创建使用 Python 调用约定的函数。 该函数在调用过程中将 *不会* 释放 GIL。" #: ../../library/ctypes.rst:1754 msgid "" "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:" msgstr "这些工厂函数所创建的函数原型可通过不同的方式来实例化,具体取决于调用中的类型与数量:" #: ../../library/ctypes.rst:1761 msgid "" "Returns a foreign function at the specified address which must be an " "integer." msgstr "在指定地址上返回一个外部函数,地址值必须为整数。" #: ../../library/ctypes.rst:1768 msgid "" "Create a C callable function (a callback function) from a Python *callable*." msgstr "基于 Python *callable* 创建一个 C 可调用函数(回调函数)。" #: ../../library/ctypes.rst:1775 msgid "" "Returns a foreign function exported by a shared library. *func_spec* must be" " a 2-tuple ``(name_or_ordinal, library)``. 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." msgstr "" "返回由一个共享库导出的外部函数。 *func_spec* 必须为一个 2 元组 ``(name_or_ordinal, library)``。 " "第一项是字符串形式的所导出函数名称,或小整数形式的所导出函数序号。 第二项是该共享库实例。" #: ../../library/ctypes.rst:1785 msgid "" "Returns a foreign function that will call a COM method. *vtbl_index* is the " "index into the virtual function table, a small non-negative integer. *name* " "is name of the COM method. *iid* is an optional pointer to the interface " "identifier which is used in extended error reporting." msgstr "" "返回将调用一个 COM 方法的外部函数。 *vtbl_index* 虚拟函数表中的索引。 *name* 是 COM 方法的名称。 *iid* " "是可选的指向接口标识符的指针,它被用于扩展的错误报告。" #: ../../library/ctypes.rst:1790 msgid "" "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 :attr:`!argtypes` tuple." msgstr "" "COM 方法使用特殊的调用约定:除了在 :attr:`!argtypes` 元组中指定的形参,它们还要求一个指向 COM 接口的指针作为第一个参数。" #: ../../library/ctypes.rst:1794 msgid "" "The optional *paramflags* parameter creates foreign function wrappers with " "much more functionality than the features described above." msgstr "可选的 *paramflags* 形参会创建相比上述特性具有更多功能的外部函数包装器。" #: ../../library/ctypes.rst:1797 msgid "" "*paramflags* must be a tuple of the same length as " ":attr:`~_CFuncPtr.argtypes`." msgstr "*paramflags* 必须为一个与 :attr:`~_CFuncPtr.argtypes` 长度相同的元组。." #: ../../library/ctypes.rst:1799 msgid "" "Each item in this tuple contains further information about a parameter, it " "must be a tuple containing one, two, or three items." msgstr "此元组中的每一项都包含有关形参的更多信息,它必须为包含一个、两个或更多条目的元组。" #: ../../library/ctypes.rst:1802 msgid "" "The first item is an integer containing a combination of direction flags for" " the parameter:" msgstr "第一项是包含形参指令旗标组合的整数。" #: ../../library/ctypes.rst:1805 msgid "1" msgstr "1" #: ../../library/ctypes.rst:1806 msgid "Specifies an input parameter to the function." msgstr "指定函数的一个输入形参。" #: ../../library/ctypes.rst:1808 msgid "2" msgstr "2" #: ../../library/ctypes.rst:1809 msgid "Output parameter. The foreign function fills in a value." msgstr "输出形参。 外部函数会填入一个值。" #: ../../library/ctypes.rst:1811 msgid "4" msgstr "4" #: ../../library/ctypes.rst:1812 msgid "Input parameter which defaults to the integer zero." msgstr "默认为整数零值的输入形参。" #: ../../library/ctypes.rst:1814 msgid "" "The optional second item is the parameter name as string. If this is " "specified, the foreign function can be called with named parameters." msgstr "可选的第二项是字符串形式的形参名称。 如果指定此项,则可以使用该形参名称来调用外部函数。" #: ../../library/ctypes.rst:1817 msgid "The optional third item is the default value for this parameter." msgstr "可选的第三项是该形参的默认值。" #: ../../library/ctypes.rst:1820 msgid "" "The following example demonstrates how to wrap the Windows ``MessageBoxW`` " "function so that it supports default parameters and named arguments. The C " "declaration from the windows header file is this::" msgstr "" "下面的例子演示了如何包装 Windows 的 ``MessageBoxW`` 函数以使其支持默认形参和命名参数。 相应的 Windows 头文件的 C " "声明是这样的::" #: ../../library/ctypes.rst:1824 msgid "" "WINUSERAPI int WINAPI\n" "MessageBoxW(\n" " HWND hWnd,\n" " LPCWSTR lpText,\n" " LPCWSTR lpCaption,\n" " UINT uType);" msgstr "" "WINUSERAPI int WINAPI\n" "MessageBoxW(\n" " HWND hWnd,\n" " LPCWSTR lpText,\n" " LPCWSTR lpCaption,\n" " UINT uType);" #: ../../library/ctypes.rst:1831 ../../library/ctypes.rst:1854 msgid "Here is the wrapping with :mod:`ctypes`::" msgstr "这是使用 :mod:`ctypes` 的包装::" #: ../../library/ctypes.rst:1833 msgid "" ">>> from ctypes import c_int, WINFUNCTYPE, windll\n" ">>> from ctypes.wintypes import HWND, LPCWSTR, UINT\n" ">>> prototype = WINFUNCTYPE(c_int, HWND, LPCWSTR, LPCWSTR, UINT)\n" ">>> paramflags = (1, \"hwnd\", 0), (1, \"text\", \"Hi\"), (1, \"caption\", \"Hello from ctypes\"), (1, \"flags\", 0)\n" ">>> MessageBox = prototype((\"MessageBoxW\", windll.user32), paramflags)" msgstr "" ">>> from ctypes import c_int, WINFUNCTYPE, windll\n" ">>> from ctypes.wintypes import HWND, LPCWSTR, UINT\n" ">>> prototype = WINFUNCTYPE(c_int, HWND, LPCWSTR, LPCWSTR, UINT)\n" ">>> paramflags = (1, \"hwnd\", 0), (1, \"text\", \"Hi\"), (1, \"caption\", \"Hello from ctypes\"), (1, \"flags\", 0)\n" ">>> MessageBox = prototype((\"MessageBoxW\", windll.user32), paramflags)" #: ../../library/ctypes.rst:1839 msgid "The ``MessageBox`` foreign function can now be called in these ways::" msgstr "现在 ``MessageBox`` 外部函数可以通过以下方式来调用::" #: ../../library/ctypes.rst:1841 msgid "" ">>> MessageBox()\n" ">>> MessageBox(text=\"Spam, spam, spam\")\n" ">>> MessageBox(flags=2, text=\"foo bar\")" msgstr "" ">>> MessageBox()\n" ">>> MessageBox(text=\"Spam, spam, spam\")\n" ">>> MessageBox(flags=2, text=\"foo bar\")" #: ../../library/ctypes.rst:1845 msgid "" "A second example demonstrates output parameters. The win32 " "``GetWindowRect`` function retrieves the dimensions of a specified window by" " copying them into ``RECT`` structure that the caller has to supply. Here " "is the C declaration::" msgstr "" "第二个例子演示了输出形参。 这个 win32 ``GetWindowRect`` 函数通过将指定窗口的维度拷贝至调用者必须提供的 ``RECT`` " "结构体来提取这些值。 这是相应的 C 声明::" #: ../../library/ctypes.rst:1849 msgid "" "WINUSERAPI BOOL WINAPI\n" "GetWindowRect(\n" " HWND hWnd,\n" " LPRECT lpRect);" msgstr "" "WINUSERAPI BOOL WINAPI\n" "GetWindowRect(\n" " HWND hWnd,\n" " LPRECT lpRect);" #: ../../library/ctypes.rst:1856 msgid "" ">>> from ctypes import POINTER, WINFUNCTYPE, windll, WinError\n" ">>> from ctypes.wintypes import BOOL, HWND, RECT\n" ">>> prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT))\n" ">>> paramflags = (1, \"hwnd\"), (2, \"lprect\")\n" ">>> GetWindowRect = prototype((\"GetWindowRect\", windll.user32), paramflags)\n" ">>>" msgstr "" ">>> from ctypes import POINTER, WINFUNCTYPE, windll, WinError\n" ">>> from ctypes.wintypes import BOOL, HWND, RECT\n" ">>> prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT))\n" ">>> paramflags = (1, \"hwnd\"), (2, \"lprect\")\n" ">>> GetWindowRect = prototype((\"GetWindowRect\", windll.user32), paramflags)\n" ">>>" #: ../../library/ctypes.rst:1863 msgid "" "Functions with output parameters will automatically return the output " "parameter 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." msgstr "" "带有输出形参的函数如果输出形参存在单一值则会自动返回该值,或是当输出形参存在多个值时返回包含这些值的元组,因此当 GetWindowRect " "被调用时现在将返回一个 RECT 实例。" #: ../../library/ctypes.rst:1868 msgid "" "Output parameters can be combined with the :attr:`~_CFuncPtr.errcheck` " "protocol to do further output processing and error checking. The win32 " "``GetWindowRect`` api function returns a ``BOOL`` to signal success or " "failure, so this function could do the error checking, and raises an " "exception when the api call failed::" msgstr "" "输出形参可以与 :attr:`~_CFuncPtr.errcheck` 协议相结合以执行进一步的输出处理和错误检查。 Win32 " "``GetWindowRect`` API 函数返回一个 ``BOOL`` 来表示成功或失败,因此该函数可以执行错误检查,并在 API " "调用失败时引发异常::" #: ../../library/ctypes.rst:1873 msgid "" ">>> def errcheck(result, func, args):\n" "... if not result:\n" "... raise WinError()\n" "... return args\n" "...\n" ">>> GetWindowRect.errcheck = errcheck\n" ">>>" msgstr "" ">>> def errcheck(result, func, args):\n" "... if not result:\n" "... raise WinError()\n" "... return args\n" "...\n" ">>> GetWindowRect.errcheck = errcheck\n" ">>>" #: ../../library/ctypes.rst:1881 msgid "" "If the :attr:`~_CFuncPtr.errcheck` function returns the argument tuple it " "receives unchanged, :mod:`ctypes` continues the normal processing it does on" " the output parameters. If you want to return a tuple of window coordinates" " instead of a ``RECT`` instance, you can retrieve the fields in the function" " and return them instead, the normal processing will no longer take place::" msgstr "" "如果 :attr:`~_CFuncPtr.errcheck` 函数原封不动地返回它所接收的参数元组,则 :mod:`ctypes` " "会继续对输出形参执行正常处理。 如果你希望返回一个窗口坐标的元组而非 ``RECT`` 实例,你可以在函数中检索字段并返回它们,正常处理将不会再执行::" #: ../../library/ctypes.rst:1887 msgid "" ">>> def errcheck(result, func, args):\n" "... if not result:\n" "... raise WinError()\n" "... rc = args[1]\n" "... return rc.left, rc.top, rc.bottom, rc.right\n" "...\n" ">>> GetWindowRect.errcheck = errcheck\n" ">>>" msgstr "" ">>> def errcheck(result, func, args):\n" "... if not result:\n" "... raise WinError()\n" "... rc = args[1]\n" "... return rc.left, rc.top, rc.bottom, rc.right\n" "...\n" ">>> GetWindowRect.errcheck = errcheck\n" ">>>" #: ../../library/ctypes.rst:1900 msgid "Utility functions" msgstr "工具函数" #: ../../library/ctypes.rst:1904 msgid "" "Returns the address of the memory buffer as integer. *obj* must be an " "instance of a ctypes type." msgstr "以整数形式返回内存缓冲区地址。 *obj* 必须为一个 ctypes 类型的实例。" #: ../../library/ctypes.rst:1907 msgid "" "Raises an :ref:`auditing event ` ``ctypes.addressof`` with " "argument ``obj``." msgstr "引发一个 :ref:`审计事件 ` ``ctypes.addressof`` 并附带参数 ``obj``。" #: ../../library/ctypes.rst:1912 msgid "" "Returns the alignment requirements of a ctypes type. *obj_or_type* must be a" " ctypes type or instance." msgstr "返回一个 ctypes 类型的对齐要求。 *obj_or_type* 必须为一个 ctypes 类型或实例。" #: ../../library/ctypes.rst:1918 msgid "" "Returns a light-weight pointer to *obj*, which must be an instance of a " "ctypes type. *offset* defaults to zero, and must be an integer that will be" " added to the internal pointer value." msgstr "" "返回指向 *obj* 的轻量指针,该对象必须为一个 ctypes 类型的实例。 *offset* 默认值为零,且必须为一个将被添加到内部指针值的整数。" #: ../../library/ctypes.rst:1922 msgid "``byref(obj, offset)`` corresponds to this C code::" msgstr "``byref(obj, offset)`` 对应于这段 C 代码::" #: ../../library/ctypes.rst:1924 msgid "(((char *)&obj) + offset)" msgstr "(((char *)&obj) + offset)" #: ../../library/ctypes.rst:1926 msgid "" "The returned object can only be used as a foreign function call parameter. " "It behaves similar to ``pointer(obj)``, but the construction is a lot " "faster." msgstr "返回的对象只能被用作外部函数调用形参。 它的行为类似于 ``pointer(obj)``,但构造起来要快很多。" #: ../../library/ctypes.rst:1932 msgid "" "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." msgstr "" "此函数类似于 C 的强制转换运算符。 它返回一个 *type* 的新实例,该实例指向与 *obj* 相同的内存块。 *type* 必须为指针类型,而 " "*obj* 必须为可以被作为指针来解读的对象。" #: ../../library/ctypes.rst:1940 msgid "" "This function creates a mutable character buffer. The returned object is a " "ctypes array of :class:`c_char`." msgstr "此函数会创建一个可变的字符缓冲区。 返回的对象是一个 :class:`c_char` 的 ctypes 数组。" #: ../../library/ctypes.rst:1943 msgid "" "*init_or_size* must be an integer which specifies the size of the array, or " "a bytes object which will be used to initialize the array items." msgstr "*init_or_size* 必须是一个指明数组大小的整数,或者是一个将被用来初始化数组条目的字节串对象。" #: ../../library/ctypes.rst:1946 msgid "" "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." msgstr "" "如果将一个字节串对象指定为第一个参数,则将使缓冲区大小比其长度多一项以便数组的最后一项为一个 NUL 终结符。 " "可以传入一个整数作为第二个参数以允许在不使用字节串长度的情况下指定数组大小。" #: ../../library/ctypes.rst:1951 msgid "" "Raises an :ref:`auditing event ` ``ctypes.create_string_buffer`` " "with arguments ``init``, ``size``." msgstr "" "引发一个 :ref:`审计事件 ` ``ctypes.create_string_buffer`` 并附带参数 ``init``, " "``size``。" #: ../../library/ctypes.rst:1956 msgid "" "This function creates a mutable unicode character buffer. The returned " "object is a ctypes array of :class:`c_wchar`." msgstr "此函数会创建一个可变的 unicode 字符缓冲区。 返回的对象是一个 :class:`c_wchar` 的 ctypes 数组。" #: ../../library/ctypes.rst:1959 msgid "" "*init_or_size* must be an integer which specifies the size of the array, or " "a string which will be used to initialize the array items." msgstr "*init_or_size* 必须是一个指明数组大小的整数,或者是一个将被用来初始化数组条目的字符串。" #: ../../library/ctypes.rst:1962 msgid "" "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." msgstr "" "如果将一个字符串指定为第一个参数,则将使缓冲区大小比其长度多一项以便数组的最后一项为一个 NUL 终结符。 " "可以传入一个整数作为第二个参数以允许在不使用字符串长度的情况下指定数组大小。" #: ../../library/ctypes.rst:1968 msgid "" "Raises an :ref:`auditing event ` ``ctypes.create_unicode_buffer`` " "with arguments ``init``, ``size``." msgstr "" "引发一个 :ref:`审计事件 ` ``ctypes.create_unicode_buffer`` 并附带参数 ``init``," " ``size``。" #: ../../library/ctypes.rst:1973 msgid "" "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." msgstr "" "此函数是一个允许使用 ctypes 实现进程内 COM 服务器的钩子。 它将由 _ctypes 扩展所导出的 DllCanUnloadNow " "函数来调用。" #: ../../library/ctypes.rst:1982 msgid "" "This function is a hook which allows implementing in-process COM servers " "with ctypes. It is called from the DllGetClassObject function that the " "``_ctypes`` extension dll exports." msgstr "" "此函数是一个允许使用 ctypes 实现进程内 COM 服务器的钩子。 它将由 ``_ctypes`` 扩展 DLL 所导出的 " "DllGetClassObject 函数来调用。" #: ../../library/ctypes.rst:1992 msgid "" "Try to find a library and return a pathname. *name* is the library name " "without any prefix like ``lib``, suffix like ``.so``, ``.dylib`` or version " "number (this is the form used for the posix linker option :option:`!-l`). " "If no library can be found, returns ``None``." msgstr "" "尝试寻找一个库并返回路径名称。 *name* 是库名称并且不带任何前缀如 ``lib`` 以及后缀如 ``.so``,``.dylib`` " "或版本号(形式与 posix 链接器选项 :option:`!-l` 所用的一致)。 如果找不到库,则返回 ``None``。" #: ../../library/ctypes.rst:2003 msgid "" "Returns the filename of the VC runtime library used by Python, and by the " "extension modules. If the name of the library cannot be determined, " "``None`` is returned." msgstr "返回 Python 以及扩展模块所使用的 VC 运行时库的文件名。 如果库名称无法确定,则返回 ``None``。" #: ../../library/ctypes.rst:2007 msgid "" "If you need to free memory, for example, allocated by an extension module " "with a call to the ``free(void *)``, it is important that you use the " "function in the same library that allocated the memory." msgstr "" "如果你需要通过调用 ``free(void *)`` 来释放内存,例如某个扩展模块所分配的内存,重要的一点是你应当使用分配内存的库中的函数。" #: ../../library/ctypes.rst:2016 msgid "" "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." msgstr "" "返回错误码 *code* 的文本描述。 如果未指定错误码,则会通过调用 Windows API 函数 GetLastError 来获取最近的错误码。" #: ../../library/ctypes.rst:2025 msgid "" "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." msgstr "" "返回 Windows 在调用线程中设置的最近的错误码。 此函数会直接调用 Windows ``GetLastError()`` 函数,它并不返回错误码的" " ctypes 私有副本。" #: ../../library/ctypes.rst:2034 msgid "" "Returns the current value of the ctypes-private copy of the system " ":data:`errno` variable in the calling thread." msgstr "返回调用线程中系统 :data:`errno` 变量的 ctypes 私有副本的当前值。" #: ../../library/ctypes.rst:2037 msgid "" "Raises an :ref:`auditing event ` ``ctypes.get_errno`` with no " "arguments." msgstr "引发一个不带参数的 :ref:`审计事件 ` ``ctypes.get_errno``。" #: ../../library/ctypes.rst:2041 msgid "" "Returns the current value of the ctypes-private copy of the system " ":data:`!LastError` variable in the calling thread." msgstr "返回调用线程中系统 :data:`!LastError` 变量的 ctypes 私有副本的当前值。" #: ../../library/ctypes.rst:2046 msgid "" "Raises an :ref:`auditing event ` ``ctypes.get_last_error`` with no" " arguments." msgstr "引发一个不带参数的 :ref:`审计事件 ` ``ctypes.get_last_error``。" #: ../../library/ctypes.rst:2051 msgid "" "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." msgstr "" "与标准 C memmove 库函数相同:将 *count* 个字节从 *src* 拷贝到 *dst*。 *dst* 和 *src* " "必须为整数或可被转换为指针的 ctypes 实例。" #: ../../library/ctypes.rst:2058 msgid "" "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." msgstr "" "与标准 C memset 库函数相同:将位于地址 *dst* 的内存块用 *count* 个字节的 *c* 值填充。 *dst* 必须为指定地址的整数或" " ctypes 实例。" #: ../../library/ctypes.rst:2065 msgid "" "Create and return 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." msgstr "" "创建并返回一个新的 ctypes 指针类型。 指针类型会被缓存并在内部重复使用,因此重复调用此函数耗费不大。 *type* 必须为 ctypes 类型。" #: ../../library/ctypes.rst:2072 msgid "" "Create a new pointer instance, pointing to *obj*. The returned object is of " "the type ``POINTER(type(obj))``." msgstr "创建一个新的指针实例,指向 *obj*。 返回的对象类型为 ``POINTER(type(obj))``。" #: ../../library/ctypes.rst:2075 msgid "" "Note: If you just want to pass a pointer to an object to a foreign function " "call, you should use ``byref(obj)`` which is much faster." msgstr "注意:如果你只是想向外部函数调用传递一个对象指针,你应当使用更为快速的 ``byref(obj)``。" #: ../../library/ctypes.rst:2081 msgid "" "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 ``sizeof(type(obj))``," " but it is possible to enlarge the buffer." msgstr "" "此函数可改变 *obj* 的内部内存缓冲区大小,其参数必须为 ctypes 类型的实例。 没有可能将缓冲区设为小于对象类型的本机大小值,该值由 " "``sizeof(type(obj))`` 给出,但将缓冲区加大则是可能的。" #: ../../library/ctypes.rst:2089 msgid "" "Set the current value of the ctypes-private copy of the system :data:`errno`" " variable in the calling thread to *value* and return the previous value." msgstr "设置调用线程中系统 :data:`errno` 变量的 ctypes 私有副本的当前值为 *value* 并返回原来的值。" #: ../../library/ctypes.rst:2092 msgid "" "Raises an :ref:`auditing event ` ``ctypes.set_errno`` with " "argument ``errno``." msgstr "引发一个 :ref:`审计事件 ` ``ctypes.set_errno`` 并附带参数 ``errno``。" #: ../../library/ctypes.rst:2097 msgid "" "Sets the current value of the ctypes-private copy of the system " ":data:`!LastError` variable in the calling thread to *value* and return the " "previous value." msgstr "在调用线程中将系统 :data:`!LastError` 变量的 ctypes 私有副本的当前值设为 *value* 并返回之前的值。" #: ../../library/ctypes.rst:2103 msgid "" "Raises an :ref:`auditing event ` ``ctypes.set_last_error`` with " "argument ``error``." msgstr "" "引发一个 :ref:`审计事件 ` ``ctypes.set_last_error`` 并附带参数 ``error``。" #: ../../library/ctypes.rst:2108 msgid "" "Returns the size in bytes of a ctypes type or instance memory buffer. Does " "the same as the C ``sizeof`` operator." msgstr "返回 ctypes 类型或实例的内存缓冲区以字节表示的大小。 其功能与 C ``sizeof`` 运算符相同。" #: ../../library/ctypes.rst:2114 msgid "" "Return the byte string at *void \\*ptr*. If *size* is specified, it is used " "as size, otherwise the string is assumed to be zero-terminated." msgstr "返回位于 *void \\*ptr* 的字节串。 如果指定了 *size*,它将被用作字节串的大小,否则将假定字节串以零值结尾。" #: ../../library/ctypes.rst:2118 msgid "" "Raises an :ref:`auditing event ` ``ctypes.string_at`` with " "arguments ``ptr``, ``size``." msgstr "" "引发一个 :ref:`审计事件 ` ``ctypes.string_at`` 并附带参数 ``ptr``, ``size``。" #: ../../library/ctypes.rst:2123 msgid "" "This function is probably the worst-named thing in ctypes. It creates an " "instance of :exc:`OSError`. If *code* is not specified, ``GetLastError`` is" " called to determine the error code. If *descr* is not specified, " ":func:`FormatError` is called to get a textual description of the error." msgstr "" "此函数可能是 ctypes 中命名得最糟糕的。 它会创建一个 :exc:`OSError` 的实例。 如果未指定 *code*,则会调用 " "``GetLastError`` 来确定错误码。 如果未指定 *descr*,则会调用 :func:`FormatError` " "来获取错误的文本描述。is called to get a textual description of the error." #: ../../library/ctypes.rst:2131 msgid "" "An instance of :exc:`WindowsError` used to be created, which is now an alias" " of :exc:`OSError`." msgstr "过去会创建 :exc:`WindowsError` 的实例,现在它是 :exc:`OSError` 的别名。" #: ../../library/ctypes.rst:2138 msgid "" "Return the wide-character string at *void \\*ptr*. If *size* is specified, " "it is used as the number of characters of the string, otherwise the string " "is assumed to be zero-terminated." msgstr "返回位于 *void \\*ptr* 的宽字符串。 如果指定了 *size*,它将被用作字符串的字符数量,否则将假定字符串以零值结尾。" #: ../../library/ctypes.rst:2143 msgid "" "Raises an :ref:`auditing event ` ``ctypes.wstring_at`` with " "arguments ``ptr``, ``size``." msgstr "" "引发一个 :ref:`审计事件 ` ``ctypes.wstring_at`` 并附带参数 ``ptr``, ``size``。" #: ../../library/ctypes.rst:2149 msgid "Data types" msgstr "数据类型" #: ../../library/ctypes.rst:2154 msgid "" "This non-public class is the common base class of all ctypes data types. " "Among other things, all ctypes type instances contain a memory block that " "hold C compatible data; the address of the memory block is returned by the " ":func:`addressof` helper function. Another instance variable is exposed as " ":attr:`_objects`; this contains other Python objects that need to be kept " "alive in case the memory block contains pointers." msgstr "" "这个非公有类是所有 ctypes 数据类型的共同基类。 另外,所有 ctypes 类型的实例都包含一个存放 C 兼容数据的内存块;该内存块的地址可由 " ":func:`addressof` 辅助函数返回。 还有一个实例变量被公开为 " ":attr:`_objects`;此变量包含其他在内存块包含指针的情况下需要保持存活的 Python 对象。" #: ../../library/ctypes.rst:2161 msgid "" "Common methods of ctypes data types, these are all class methods (to be " "exact, they are methods of the :term:`metaclass`):" msgstr "ctypes 数据类型的通用方法,它们都是类方法(严谨地说,它们是 :term:`metaclass` 的方法):" #: ../../library/ctypes.rst:2166 msgid "" "This method returns a ctypes instance that shares the buffer of the *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 " ":exc:`ValueError` is raised." msgstr "" "此方法返回一个共享 *source* 对象缓冲区的 ctypes 实例。 *source* 对象必须支持可写缓冲区接口。 可选的 *offset* " "形参指定以字节表示的源缓冲区内偏移量;默认值为零。 如果源缓冲区不够大则会引发 :exc:`ValueError`。" #: ../../library/ctypes.rst:2172 ../../library/ctypes.rst:2182 msgid "" "Raises an :ref:`auditing event ` ``ctypes.cdata/buffer`` with " "arguments ``pointer``, ``size``, ``offset``." msgstr "" "引发一个 :ref:`审计事件 ` ``ctypes.cdata/buffer`` 并附带参数 ``pointer``, " "``size``, ``offset``。" #: ../../library/ctypes.rst:2176 msgid "" "This method creates a ctypes instance, copying the buffer from the *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 :exc:`ValueError` is raised." msgstr "" "此方法创建一个 ctypes 实例,从 *source* 对象缓冲区拷贝缓冲区,该对象必须是可读的。 可选的 *offset* " "形参指定以字节表示的源缓冲区内偏移量;默认值为零。 如果源缓冲区不够大则会引发 :exc:`ValueError`。" #: ../../library/ctypes.rst:2186 msgid "" "This method returns a ctypes type instance using the memory specified by " "*address* which must be an integer." msgstr "此方法会使用 *address* 所指定的内存返回一个 ctypes 类型的实例,该参数必须为一个整数。" #: ../../library/ctypes.rst:2189 ../../library/ctypes.rst:2191 msgid "" "This method, and others that indirectly call this method, raises an " ":ref:`auditing event ` ``ctypes.cdata`` with argument ``address``." msgstr "" "这个方法以及其他间接调用了它的方法会引发一个 :ref:`审计事件 ` ``ctypes.cdata``,附带参数 " "``address``。" #: ../../library/ctypes.rst:2197 msgid "" "This method adapts *obj* to a ctypes type. It is called with the actual " "object used in a foreign function call when the type is present in the " "foreign function's :attr:`~_CFuncPtr.argtypes` tuple; it must return an " "object that can be used as a function call parameter." msgstr "" "此方法会将 *obj* 适配为一个 ctypes 类型。 当该类型出现在外部函数的 :attr:`~_CFuncPtr.argtypes` " "元组中时它将会被调用并传入在外部函数中使用的实际对象;它必须返回一个可被用作函数调用形参的对象。" #: ../../library/ctypes.rst:2202 msgid "" "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." msgstr "" "所有 ctypes 数据类型都带有这个类方法的默认实现,它通常会返回 *obj*,如果该对象是此类型的实例的话。 某些类型也能接受其他对象。" #: ../../library/ctypes.rst:2208 msgid "" "This method returns a ctypes type instance exported by a shared library. " "*name* is the name of the symbol that exports the data, *library* is the " "loaded shared library." msgstr "此方法返回一个由共享库导出的 ctypes 类型。 *name* 为导出数据的符号名称,*library* 为所加载的共享库。" #: ../../library/ctypes.rst:2212 msgid "Common instance variables of ctypes data types:" msgstr "ctypes 数据类型的通用实例变量:" #: ../../library/ctypes.rst:2216 msgid "" "Sometimes ctypes data instances do not own the memory block they contain, " "instead they share part of the memory block of a base object. The " ":attr:`_b_base_` read-only member is the root ctypes object that owns the " "memory block." msgstr "" "有时 ctypes 数据实例并不拥有它们所包含的内存块,它们只是共享了某个基对象的部分内存块。 :attr:`_b_base_` " "只读成员是拥有内存块的根 ctypes 对象。" #: ../../library/ctypes.rst:2223 msgid "" "This read-only variable is true when the ctypes data instance has allocated " "the memory block itself, false otherwise." msgstr "这个只读变量在 ctypes 数据实例自身已分配了内存块时为真值,否则为假值。" #: ../../library/ctypes.rst:2228 msgid "" "This member is either ``None`` or a dictionary containing Python objects " "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." msgstr "" "这个成员或者为 ``None``,或者为一个包含需要保持存活以使内存块的内存保持有效的 Python 对象的字典。 " "这个对象只是出于调试目的而对外公开;绝对不要修改此字典的内容。" #: ../../library/ctypes.rst:2241 msgid "" "This non-public class is the base class of all fundamental ctypes data " "types. It is mentioned here because it contains the common attributes of the" " fundamental ctypes data types. :class:`_SimpleCData` is a subclass of " ":class:`_CData`, so it inherits their methods and attributes. ctypes data " "types that are not and do not contain pointers can now be pickled." msgstr "" "这个非公有类是所有基本 ctypes 数据类型的基类。 它在这里被提及是因为它包含基本 ctypes 数据类型共有的属性。 " ":class:`_SimpleCData` 是 :class:`_CData` 的子类,因此继承了其方法和属性。 非指针及不包含指针的 ctypes " "数据类型现在将可以被封存。" #: ../../library/ctypes.rst:2247 msgid "Instances have a single attribute:" msgstr "实例拥有一个属性:" #: ../../library/ctypes.rst:2251 msgid "" "This attribute contains the actual value of the instance. For integer and " "pointer types, it is an integer, for character types, it is a single " "character bytes object or string, for character pointer types it is a Python" " bytes object or string." msgstr "" "这个属性包含实例的实际值。 对于整数和指针类型,它是一个整数,对于字符类型,它是一个单字符字符串对象或字符串,对于字符指针类型,它是一个 Python " "字节串对象或字符串。" #: ../../library/ctypes.rst:2256 msgid "" "When the ``value`` attribute is retrieved from a ctypes instance, usually a " "new object is returned each time. :mod:`ctypes` does *not* implement " "original object return, always a new object is constructed. The same is " "true for all other ctypes object instances." msgstr "" "当从 ctypes 实例提取 ``value`` 属性时,通常每次会返回一个新的对象。 :mod:`ctypes` 并 *没有* " "实现原始对象返回,它总是会构造一个新的对象。 所有其他 ctypes 对象实例也同样如此。" #: ../../library/ctypes.rst:2262 msgid "" "Fundamental data types, when returned as foreign function call results, or, " "for 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 :attr:`~_CFuncPtr.restype` of :class:`c_char_p`, you " "will always receive a Python bytes object, *not* a :class:`c_char_p` " "instance." msgstr "" "当作为外部函数调用结果,或者举例来说,作为结构字段成员或数组条目被提取时,基本数据类型会被透明与转换为原生 Python 类型。 " "换句话说,如果某个外部函数的 :attr:`~_CFuncPtr.restype` 是 :class:`c_char_p`,那么你将总是得到一个 " "Python 字节串对象,而 *不是* 一个 :class:`c_char_p` 实例。" #: ../../library/ctypes.rst:2270 msgid "" "Subclasses of fundamental data types do *not* inherit this behavior. So, if " "a foreign functions :attr:`!restype` is a subclass of :class:`c_void_p`, 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 ``value`` " "attribute." msgstr "" "基本数据类型的子类 *不会* 继承这种行为。 因此,如果一个外部函数的 :attr:`!restype` 是 :class:`c_void_p` " "的子类,则你将从函数调用得到一个该子类的实例。 当然,你可以通过访问 ``value`` 属性来获取指针的值。" #: ../../library/ctypes.rst:2275 msgid "These are the fundamental ctypes data types:" msgstr "这些是基本 ctypes 数据类型:" #: ../../library/ctypes.rst:2279 msgid "" "Represents the C :c:expr:`signed char` datatype, and interprets the value as" " small integer. The constructor accepts an optional integer initializer; no" " overflow checking is done." msgstr "" "代表 C :c:expr:`signed char` 数据类型,并将值解读为一个小整数。 该构造器接受一个可选的整数初始值;不会执行溢出检查。" #: ../../library/ctypes.rst:2286 msgid "" "Represents the C :c:expr:`char` 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." msgstr "" "代表 C :c:expr:`char` 数据类型,并将值解读为单个字符。 该构造器接受一个可选的字符串初始值,字符串的长度必须恰好为一个字符。" #: ../../library/ctypes.rst:2293 msgid "" "Represents the C :c:expr:`char *` datatype when it points to a zero-" "terminated string. For a general character pointer that may also point to " "binary data, ``POINTER(c_char)`` must be used. The constructor accepts an " "integer address, or a bytes object." msgstr "" "当指向一个以零为结束符的字符串时代表 C :c:expr:`char *` 数据类型。 对于通用字符指针来说也可能指向二进制数据,必须要使用 " "``POINTER(c_char)``。 该构造器接受一个整数地址,或者一个字节串对象。" #: ../../library/ctypes.rst:2301 msgid "" "Represents the C :c:expr:`double` datatype. The constructor accepts an " "optional float initializer." msgstr "代表 C :c:expr:`double` 数据类型。 该构造器接受一个可选的浮点数初始值。" #: ../../library/ctypes.rst:2307 msgid "" "Represents the C :c:expr:`long double` datatype. The constructor accepts an" " optional float initializer. On platforms where ``sizeof(long double) == " "sizeof(double)`` it is an alias to :class:`c_double`." msgstr "" "代表 C :c:expr:`long double` 数据类型。 该构造器接受一个可选的浮点数初始值。 在 ``sizeof(long double) " "== sizeof(double)`` 的平台上它是 :class:`c_double` 的一个别名。" #: ../../library/ctypes.rst:2313 msgid "" "Represents the C :c:expr:`float` datatype. The constructor accepts an " "optional float initializer." msgstr "" "代表 C :c:expr:`float` 数据类型。 该构造器接受一个可选的浮点数初始值。datatype. The constructor " "accepts an optional float initializer." #: ../../library/ctypes.rst:2319 msgid "" "Represents the C :c:expr:`signed int` datatype. The constructor accepts an " "optional integer initializer; no overflow checking is done. On platforms " "where ``sizeof(int) == sizeof(long)`` it is an alias to :class:`c_long`." msgstr "" "代表 C :c:expr:`signed int` 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。 在 ``sizeof(int) " "== sizeof(long)`` 的平台上它是 :class:`c_long` 的一个别名。" #: ../../library/ctypes.rst:2326 msgid "" "Represents the C 8-bit :c:expr:`signed int` datatype. Usually an alias for " ":class:`c_byte`." msgstr "代表 C 8 位 :c:expr:`signed int` 数据类型。 通常是 :class:`c_byte` 的一个别名。" #: ../../library/ctypes.rst:2332 msgid "" "Represents the C 16-bit :c:expr:`signed int` datatype. Usually an alias for" " :class:`c_short`." msgstr "代表 C 16 位 :c:expr:`signed int` 数据类型。 通常是 :class:`c_short` 的一个别名。" #: ../../library/ctypes.rst:2338 msgid "" "Represents the C 32-bit :c:expr:`signed int` datatype. Usually an alias for" " :class:`c_int`." msgstr "代表 C 32 位 :c:expr:`signed int` 数据类型。 通常是 :class:`c_int` 的一个别名。" #: ../../library/ctypes.rst:2344 msgid "" "Represents the C 64-bit :c:expr:`signed int` datatype. Usually an alias for" " :class:`c_longlong`." msgstr "代表 C 64 位 :c:expr:`signed int` 数据类型。 通常是 :class:`c_longlong` 的一个别名。" #: ../../library/ctypes.rst:2350 msgid "" "Represents the C :c:expr:`signed long` datatype. The constructor accepts an" " optional integer initializer; no overflow checking is done." msgstr "代表 C :c:expr:`signed long` 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。" #: ../../library/ctypes.rst:2356 msgid "" "Represents the C :c:expr:`signed long long` datatype. The constructor " "accepts an optional integer initializer; no overflow checking is done." msgstr "代表 C :c:expr:`signed long long` 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。" #: ../../library/ctypes.rst:2362 msgid "" "Represents the C :c:expr:`signed short` datatype. The constructor accepts " "an optional integer initializer; no overflow checking is done." msgstr "代表 C :c:expr:`signed short` 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。" #: ../../library/ctypes.rst:2368 msgid "Represents the C :c:type:`size_t` datatype." msgstr "代表 C :c:type:`size_t` 数据类型。" #: ../../library/ctypes.rst:2373 msgid "Represents the C :c:type:`ssize_t` datatype." msgstr "代表 C :c:type:`ssize_t` 数据类型。" #: ../../library/ctypes.rst:2380 msgid "Represents the C :c:type:`time_t` datatype." msgstr "代表 C :c:type:`time_t` 数据类型。" #: ../../library/ctypes.rst:2387 msgid "" "Represents the C :c:expr:`unsigned char` datatype, it interprets the value " "as small integer. The constructor accepts an optional integer initializer; " "no overflow checking is done." msgstr "" "代表 C :c:expr:`unsigned char` 数据类型,它将值解读为一个小整数。 该构造器接受一个可选的整数初始值;不会执行溢出检查。" #: ../../library/ctypes.rst:2394 msgid "" "Represents the C :c:expr:`unsigned int` datatype. The constructor accepts " "an optional integer initializer; no overflow checking is done. On platforms" " where ``sizeof(int) == sizeof(long)`` it is an alias for :class:`c_ulong`." msgstr "" "代表 C :c:expr:`unsigned int` 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。 在 ``sizeof(int)" " == sizeof(long)`` 的平台上它是 :class:`c_ulong` 的一个别名。" #: ../../library/ctypes.rst:2401 msgid "" "Represents the C 8-bit :c:expr:`unsigned int` datatype. Usually an alias " "for :class:`c_ubyte`." msgstr "代表 C 8 位 :c:expr:`unsigned int` 类型。 通常是 :class:`c_ubyte` 的一个别名。." #: ../../library/ctypes.rst:2407 msgid "" "Represents the C 16-bit :c:expr:`unsigned int` datatype. Usually an alias " "for :class:`c_ushort`." msgstr "代表 C 16 位 :c:expr:`unsigned int` 数据类型。 通常是 :class:`c_ushort` 的一个别名。." #: ../../library/ctypes.rst:2413 msgid "" "Represents the C 32-bit :c:expr:`unsigned int` datatype. Usually an alias " "for :class:`c_uint`." msgstr "代表 C 32 位 :c:expr:`unsigned int` 数据类型。 通常是 :class:`c_uint` 的一个别名。" #: ../../library/ctypes.rst:2419 msgid "" "Represents the C 64-bit :c:expr:`unsigned int` datatype. Usually an alias " "for :class:`c_ulonglong`." msgstr "" "代表 C 64 位 :c:expr:`unsigned int` 数据类型。 通常是 :class:`c_ulonglong` 的一个别名。" #: ../../library/ctypes.rst:2425 msgid "" "Represents the C :c:expr:`unsigned long` datatype. The constructor accepts " "an optional integer initializer; no overflow checking is done." msgstr "代表 C :c:expr:`unsigned long` 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。" #: ../../library/ctypes.rst:2431 msgid "" "Represents the C :c:expr:`unsigned long long` datatype. The constructor " "accepts an optional integer initializer; no overflow checking is done." msgstr "代表 C :c:expr:`unsigned long long` 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。" #: ../../library/ctypes.rst:2437 msgid "" "Represents the C :c:expr:`unsigned short` datatype. The constructor accepts" " an optional integer initializer; no overflow checking is done." msgstr "代表 C :c:expr:`unsigned short` 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。" #: ../../library/ctypes.rst:2443 msgid "" "Represents the C :c:expr:`void *` type. The value is represented as " "integer. The constructor accepts an optional integer initializer." msgstr "代表 C :c:expr:`void *` 类型。 该值被表示为整数形式。 该构造器接受一个可选的整数初始值。" #: ../../library/ctypes.rst:2449 msgid "" "Represents the C :c:type:`wchar_t` 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." msgstr "" "代表 C :c:type:`wchar_t` 数据类型,并将值解读为一单个字符的 unicode 字符串。 " "该构造器接受一个可选的字符串初始化器,字符串的长度必须恰好为一个字符。" #: ../../library/ctypes.rst:2456 msgid "" "Represents the C :c:expr:`wchar_t *` datatype, which must be a pointer to a " "zero-terminated wide character string. The constructor accepts an integer " "address, or a string." msgstr "" "代表 C :c:expr:`wchar_t *` 数据类型,它必须为指向以零为续签符的宽字符串的指针。 该构造器接受一个整数地址,或一个字符串。" #: ../../library/ctypes.rst:2463 msgid "" "Represent the C :c:expr:`bool` datatype (more accurately, :c:expr:`_Bool` " "from C99). Its value can be ``True`` or ``False``, and the constructor " "accepts any object that has a truth value." msgstr "" "代表 C :c:expr:`bool` 数据类型 (更准确地说,是 C99 :c:expr:`_Bool`)。 它的值可以为 ``True`` 或 " "``False``,并且该构造器接受任何具有逻辑值的对象。" #: ../../library/ctypes.rst:2470 msgid "" "Represents a :c:type:`!HRESULT` value, which contains success or error " "information for a function or method call." msgstr "代表一个 :c:type:`!HRESULT` 值,它包含某个函数或方法调用的成功或错误信息。" #: ../../library/ctypes.rst:2478 msgid "" "Represents the C :c:expr:`PyObject *` datatype. Calling this without an " "argument creates a ``NULL`` :c:expr:`PyObject *` pointer." msgstr "" "代表 C :c:expr:`PyObject *` 数据类型。 不带参数地调用此构造器将创建一个 ``NULL`` :c:expr:`PyObject " "*` 指针。" #: ../../library/ctypes.rst:2481 msgid "" "The :mod:`!ctypes.wintypes` module provides quite some other Windows " "specific data types, for example :c:type:`!HWND`, :c:type:`!WPARAM`, or " ":c:type:`!DWORD`. Some useful structures like :c:type:`!MSG` or " ":c:type:`!RECT` are also defined." msgstr "" ":mod:`!ctypes.wintypes` 模块提供了其他许多 Windows 专属的数据类型,例如 :c:type:`!HWND`, " ":c:type:`!WPARAM` 或 :c:type:`!DWORD`。 还定义了一些有用的结构体如 :c:type:`!MSG` 或 " ":c:type:`!RECT`。" #: ../../library/ctypes.rst:2489 msgid "Structured data types" msgstr "结构化数据类型" #: ../../library/ctypes.rst:2494 msgid "Abstract base class for unions in native byte order." msgstr "本机字节序的联合所对应的抽象基类。" #: ../../library/ctypes.rst:2499 msgid "Abstract base class for unions in *big endian* byte order." msgstr "*大端* 字节序的联合所对应的抽象基类。" #: ../../library/ctypes.rst:2505 msgid "Abstract base class for unions in *little endian* byte order." msgstr "*小端* 字节序的联合所对应的抽象基类。" #: ../../library/ctypes.rst:2511 msgid "Abstract base class for structures in *big endian* byte order." msgstr "*大端* 字节序的结构体所对应的抽象基类。" #: ../../library/ctypes.rst:2516 msgid "Abstract base class for structures in *little endian* byte order." msgstr "*小端* 字节序的结构体所对应的抽象基类。" #: ../../library/ctypes.rst:2518 msgid "" "Structures and unions with non-native byte order cannot contain pointer type" " fields, or any other data types containing pointer type fields." msgstr "非本机字节序的结构体和联合不能包含指针类型字段,或任何其他包含指针类型字段的数据类型。" #: ../../library/ctypes.rst:2524 msgid "Abstract base class for structures in *native* byte order." msgstr "*本机* 字节序的结构体所对应的抽象基类。" #: ../../library/ctypes.rst:2526 msgid "" "Concrete structure and union types must be created by subclassing one of " "these types, and at least define a :attr:`_fields_` class variable. " ":mod:`ctypes` will create :term:`descriptor`\\s which allow reading and " "writing the fields by direct attribute accesses. These are the" msgstr "" "实际的结构体和联合类型必须通过子类化这些类型之一来创建,并且至少要定义一个 :attr:`_fields_` 类变量。 :mod:`ctypes` " "将创建 :term:`descriptor`,它允许通过直接属性访问来读取和写入字段。 这些是" #: ../../library/ctypes.rst:2534 msgid "" "A sequence defining the structure fields. The items must be 2-tuples or " "3-tuples. The first item is the name of the field, the second item " "specifies the type of the field; it can be any ctypes data type." msgstr "" "一个定义结构体字段的序列。 其中的条目必须为 2 元组或 3 元组。 元组的第一项是字段名称,第二项指明字段类型;它可以是任何 ctypes 数据类型。" #: ../../library/ctypes.rst:2538 msgid "" "For integer type fields like :class:`c_int`, a third optional item can be " "given. It must be a small positive integer defining the bit width of the " "field." msgstr "对于整数类型字段例如 :class:`c_int`,可以给定第三个可选项。 它必须是一个定义字段比特位宽度的小正整数。" #: ../../library/ctypes.rst:2542 msgid "" "Field names must be unique within one structure or union. This is not " "checked, only one field can be accessed when names are repeated." msgstr "字段名称在一个结构体或联合中必须唯一。 不会检查这个唯一性,但当名称出现重复时将只有一个字段可被访问。" #: ../../library/ctypes.rst:2545 msgid "" "It is possible to define the :attr:`_fields_` class variable *after* the " "class statement that defines the Structure subclass, this allows creating " "data types that directly or indirectly reference themselves::" msgstr "" "可以在定义 Structure 子类的类语句 *之后* 再定义 :attr:`_fields_` 类变量,这将允许创建直接或间接引用其自身的数据类型::" #: ../../library/ctypes.rst:2549 msgid "" "class List(Structure):\n" " pass\n" "List._fields_ = [(\"pnext\", POINTER(List)),\n" " ...\n" " ]" msgstr "" "class List(Structure):\n" " pass\n" "List._fields_ = [(\"pnext\", POINTER(List)),\n" " ...\n" " ]" #: ../../library/ctypes.rst:2555 msgid "" "The :attr:`_fields_` class variable must, however, be defined before the " "type is first used (an instance is created, :func:`sizeof` is called on it, " "and so on). Later assignments to the :attr:`_fields_` class variable will " "raise an AttributeError." msgstr "" "但是,:attr:`_fields_` 类变量必须在类型第一次被使用(创建实例,调用 :func:`sizeof` 等等)之前进行定义。 在此之后对 " ":attr:`_fields_` 类变量赋值将会引发 AttributeError。" #: ../../library/ctypes.rst:2560 msgid "" "It is possible to define sub-subclasses of structure types, they inherit the" " fields of the base class plus the :attr:`_fields_` defined in the sub-" "subclass, if any." msgstr "可以定义结构体类型的子类,它们会继承基类的字段再加上在子类中定义的任何 :attr:`_fields_`。" #: ../../library/ctypes.rst:2567 msgid "" "An optional small integer that allows overriding the alignment of structure " "fields in the instance. :attr:`_pack_` must already be defined when " ":attr:`_fields_` is assigned, otherwise it will have no effect. Setting this" " attribute to 0 is the same as not setting it at all." msgstr "" "一个可选的小整数,它允许覆盖实例中结构体字段的对齐方式。 当 :attr:`_fields_` 被赋值时必须已经定义了 " ":attr:`_pack_`,否则它将没有效果。 将该属性设为 0 的效果与不设置它一样。" #: ../../library/ctypes.rst:2575 msgid "" "An optional sequence that lists the names of unnamed (anonymous) fields. " ":attr:`_anonymous_` must be already defined when :attr:`_fields_` is " "assigned, otherwise it will have no effect." msgstr "" "一个可选的序列,它会列出未命名(匿名)字段的名称。 当 :attr:`_fields_` 被赋值时必须已经定义了 " ":attr:`_anonymous_`,否则它将没有效果。" #: ../../library/ctypes.rst:2579 msgid "" "The fields listed in this variable must be structure or union type fields. " ":mod:`ctypes` will create descriptors in the structure type that allows " "accessing the nested fields directly, without the need to create the " "structure or union field." msgstr "" "在此变量中列出的字段必须为结构体或联合类型字段。 :mod:`ctypes` " "将在结构体类型中创建描述器以允许直接访问嵌套字段,而无需创建对应的结构体或联合字段。" #: ../../library/ctypes.rst:2584 msgid "Here is an example type (Windows)::" msgstr "以下是一个示例类型(Windows)::" #: ../../library/ctypes.rst:2586 msgid "" "class _U(Union):\n" " _fields_ = [(\"lptdesc\", POINTER(TYPEDESC)),\n" " (\"lpadesc\", POINTER(ARRAYDESC)),\n" " (\"hreftype\", HREFTYPE)]\n" "\n" "class TYPEDESC(Structure):\n" " _anonymous_ = (\"u\",)\n" " _fields_ = [(\"u\", _U),\n" " (\"vt\", VARTYPE)]" msgstr "" "class _U(Union):\n" " _fields_ = [(\"lptdesc\", POINTER(TYPEDESC)),\n" " (\"lpadesc\", POINTER(ARRAYDESC)),\n" " (\"hreftype\", HREFTYPE)]\n" "\n" "class TYPEDESC(Structure):\n" " _anonymous_ = (\"u\",)\n" " _fields_ = [(\"u\", _U),\n" " (\"vt\", VARTYPE)]" #: ../../library/ctypes.rst:2597 msgid "" "The ``TYPEDESC`` structure describes a COM data type, the ``vt`` field " "specifies which one of the union fields is valid. Since the ``u`` field is " "defined as anonymous field, it is now possible to access the members " "directly off the TYPEDESC instance. ``td.lptdesc`` and ``td.u.lptdesc`` are " "equivalent, but the former is faster since it does not need to create a " "temporary union instance::" msgstr "" "``TYPEDESC`` 结构体描述了一个 COM 数据类型,``vt`` 字段指明哪个联合字段是有效的。 由于 ``u`` " "字段被定义为匿名字段,现在可以直接从 TYPEDESC 实例访问成员。 ``td.lptdesc`` 和 ``td.u.lptdesc`` " "是等价的,但前者速度更快,因为它不需要创建临时的联合实例::" #: ../../library/ctypes.rst:2604 msgid "" "td = TYPEDESC()\n" "td.vt = VT_PTR\n" "td.lptdesc = POINTER(some_type)\n" "td.u.lptdesc = POINTER(some_type)" msgstr "" "td = TYPEDESC()\n" "td.vt = VT_PTR\n" "td.lptdesc = POINTER(some_type)\n" "td.u.lptdesc = POINTER(some_type)" #: ../../library/ctypes.rst:2609 msgid "" "It is possible to define sub-subclasses of structures, they inherit the " "fields of the base class. If the subclass definition has a separate " ":attr:`_fields_` variable, the fields specified in this are appended to the " "fields of the base class." msgstr "" "可以定义结构体的子类,它们会继承基类的字段。 如果子类定义具有单独的 :attr:`_fields_` 变量,在其中指定的字段会被添加到基类的字段中。" #: ../../library/ctypes.rst:2614 msgid "" "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 :attr:`_fields_`. Keyword arguments in " "the constructor are interpreted as attribute assignments, so they will " "initialize :attr:`_fields_` with the same name, or create new attributes for" " names not present in :attr:`_fields_`." msgstr "" "结构体和联合的构造器均可接受位置和关键字参数。 位置参数用于按照 :attr:`_fields_` 中的出现顺序来初始化成员字段。 " "构造器中的关键字参数会被解读为属性赋值,因此它们将以相应的名称来初始化 :attr:`_fields_`,或为不存在于 :attr:`_fields_`" " 中的名称创建新的属性。" #: ../../library/ctypes.rst:2625 msgid "Arrays and pointers" msgstr "数组与指针" #: ../../library/ctypes.rst:2629 msgid "Abstract base class for arrays." msgstr "数组的抽象基类。" #: ../../library/ctypes.rst:2631 msgid "" "The recommended way to create concrete array types is by multiplying any " ":mod:`ctypes` data type with a non-negative integer. Alternatively, you can" " subclass this type and define :attr:`_length_` and :attr:`_type_` 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" " :class:`Array`." msgstr "" "创建实体数组类型的推荐方式是通过将任意 :mod:`ctypes` 数据类型与一个非负整数相乘。 作为替代方式,你也可以子类化这个类型并定义 " ":attr:`_length_` 和 :attr:`_type_` 类变量。 数组元素可使用标准的抽取和切片操作来进行读写;对于切片读取,结果对象本身 " "*不是* 一个 :class:`Array`。" #: ../../library/ctypes.rst:2641 msgid "" "A positive integer specifying the number of elements in the array. Out-of-" "range subscripts result in an :exc:`IndexError`. Will be returned by " ":func:`len`." msgstr "一个指明数组中元素数量的正整数。 超出范围的抽取会导致 :exc:`IndexError`。 该值将由 :func:`len` 返回。" #: ../../library/ctypes.rst:2648 msgid "Specifies the type of each element in the array." msgstr "指明数组中每个元素的类型。" #: ../../library/ctypes.rst:2651 msgid "" "Array subclass constructors accept positional arguments, used to initialize " "the elements in order." msgstr "Array 子类构造器可接受位置参数,用来按顺序初始化元素。" #: ../../library/ctypes.rst:2657 msgid "Private, abstract base class for pointers." msgstr "私有对象,指针的抽象基类。" #: ../../library/ctypes.rst:2659 msgid "" "Concrete pointer types are created by calling :func:`POINTER` with the type " "that will be pointed to; this is done automatically by :func:`pointer`." msgstr "实际的指针类型是通过调用 :func:`POINTER` 并附带其将指向的类型来创建的;这会由 :func:`pointer` 自动完成。" #: ../../library/ctypes.rst:2663 msgid "" "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 " ":func:`len` will raise :exc:`TypeError`. 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)." msgstr "" "如果一个指针指向的是数组,则其元素可使用标准的抽取和切片方式来读写。 指针对象没有长度,因此 :func:`len` 将引发 " ":exc:`TypeError`。 抽取负值将会从指针 *之前* 的内存中读取(与 C " "一样),并且超出范围的抽取将可能因非法访问而导致崩溃(视你的运气而定)。" #: ../../library/ctypes.rst:2673 msgid "Specifies the type pointed to." msgstr "指明所指向的类型。" #: ../../library/ctypes.rst:2677 msgid "" "Returns the object to which to pointer points. Assigning to this attribute " "changes the pointer to point to the assigned object." msgstr "返回指针所指向的对象。 对此属性赋值会使指针改为指向所赋值的对象。"