ctypes

您所在的位置:网站首页 Python引用dll ctypes

ctypes

2024-07-02 23:56| 来源: 网络整理| 查看: 265

ctypes 参考手册¶ 寻找动态链接库¶

在编译型语言中,动态链接库会在编译、链接或者程序运行时访问。

The purpose of the 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.

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

ctypes.util.find_library(name)

尝试寻找一个库然后返回其路径名, name 是库名称, 且去除了 lib 等前缀和 .so 、 .dylib 、版本号等后缀(这是 posix 连接器 -l 选项使用的格式)。如果没有找到对应的库,则返回 None 。

确切的功能取决于系统。

在 Linux 上, find_library() 会尝试运行外部程序(/sbin/ldconfig, gcc, objdump 以及 ld) 来寻找库文件。返回库文件的文件名。

在 3.6 版更改: 在Linux 上,如果其他方式找不到的话,会使用环境变量 LD_LIBRARY_PATH 搜索动态链接库。

这是一些例子:

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

在 OS X 上, find_library() 会尝试几种预定义的命名方案和路径来查找库,如果成功,则返回完整的路径名:

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

在 Windows 上, find_library() 在系统路径中搜索,然后返回全路径,但是如果没有预定义的命名方案, find_library("c") 调用会返回 None

使用 ctypes 包装动态链接库,更好的方式 可能 是在开发的时候就确定名称,然后硬编码到包装模块中去,而不是在运行时使用 find_library() 寻找库。

加载动态链接库¶

有很多方式可以将动态链接库加载到 Python 进程。其中之一是实例化以下类的其中一个:

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

此类的实例即已加载的动态链接库。库中的函数使用标准 C 调用约定,并假定返回 int 。

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

仅 Windows : 此类的实例即加载好的动态链接库,其中的函数使用 stdcall 调用约定,并且假定返回 windows 指定的 HRESULT 返回码。 HRESULT 的值包含的信息说明函数调用成功还是失败,以及额外错误码。 如果返回值表示失败,会自动抛出 OSError 异常。

在 3.3 版更改: 以前是引发 WindowsError。

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

仅 Windows: 此类的实例即加载好的动态链接库,其中的函数使用 stdcall 调用约定,并假定默认返回 int 。

在 Windows CE 上,只能使用 stdcall 调用约定,为了方便, WinDLL 和 OleDLL 在这个平台上都使用标准调用约定。

调用动态库导出的函数之前,Python会释放 global interpreter lock ,并在调用后重新获取。

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

这个类实例的行为与 CDLL 类似,只不过 不会 在调用函数的时候释放 GIL 锁,且调用结束后会检查 Python 错误码。 如果错误码被设置,会抛出一个 Python 异常。

所以,它只在直接调用 Python C 接口函数的时候有用。

通过使用至少一个参数(共享库的路径名)调用它们,可以实例化所有这些类。也可以传入一个已加载的动态链接库作为 handler 参数,其他情况会调用系统底层的 dlopen 或 LoadLibrary 函数将库加载到进程,并获取其句柄。

mode 可以指定库加载方式。详情请参见 dlopen(3) 手册页。 在 Windows 上, 会忽略 mode ,在 posix 系统上, 总是会加上 RTLD_NOW ,且无法配置。

use_errno 参数如果设置为 true,可以启用ctypes的机制,通过一种安全的方法获取系统的 errno 错误码。 ctypes 维护了一个线程局部变量,它是系统 errno 的一份拷贝;如果调用了使用 use_errno=True 创建的外部函数, errno 的值会与 ctypes 自己拷贝的那一份进行交换,函数执行完后立即再交换一次。

The function ctypes.get_errno() returns the value of the ctypes private copy, and the function ctypes.set_errno() changes the ctypes private copy to a new value and returns the former value.

use_last_error 参数如果设置为 true,可以在 Windows 上启用相同的策略,它是通过 Windows API 函数 GetLastError()  和 SetLastError() 管理的。 ctypes.get_last_error() 和 ctypes.set_last_error() 可用于获取和设置 ctypes 自己维护的 windows 错误码拷贝。

ctypes.RTLD_GLOBAL

用于 mode 参数的标识值。在此标识不可用的系统上,它被定义为整数0。

ctypes.RTLD_LOCAL

Flag to use as mode parameter. On platforms where this is not available, it is the same as RTLD_GLOBAL.

ctypes.DEFAULT_MODE

加载动态链接库的默认模式。在 OSX 10.3 上,它是 RTLD_GLOBAL ,其余系统上是 RTLD_LOCAL 。

这些类的实例没有共用方法。动态链接库的导出函数可以通过属性或者数组下标的方式访问。注意,通过属性的方式访问会缓存这个函数,因而每次访问它时返回的都是同一个对象。另一方面,通过数组下标访问,每次都会返回一个新的对象:

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

还有下面这些属性可用,他们的名称以下划线开头,以避免和导出函数重名:

PyDLL._handle¶

用于访问库的系统句柄。

PyDLL._name¶

传入构造函数的库名称。

共享库也可以通用使用一个预制对象来加载,这种对象是 LibraryLoader 类的实例,具体做法或是通过调用 LoadLibrary() 方法,或是通过将库作为加载实例的属性来提取。

class ctypes.LibraryLoader(dlltype)¶

加载共享库的类。 dlltype 应当为 CDLL, PyDLL, WinDLL 或 OleDLL 类型之一。

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

LoadLibrary(name)¶

加载一个共享库到进程中并将其返回。 此方法总是返回一个新的库实例。

可用的预制库加载器有如下这些:

ctypes.cdll

创建 CDLL 实例。

ctypes.windll

仅Windows中: 创建 WinDLL 实例.

ctypes.oledll

仅Windows中: 创建 OleDLL 实例。

ctypes.pydll

创建 PyDLL 实例。

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

ctypes.pythonapi

一个 PyDLL 的实例,它将 Python C API 函数作为属性公开。 请注意所有这些函数都应返回 C int,当然这也不是绝对的,因此你必须分配正确的 restype 属性以使用这些函数。

外部函数¶

正如之前小节的说明,外部函数可作为被加载共享库的属性来访问。 用此方式创建的函数对象默认接受任意数量的参数,接受任意 ctypes 数据实例作为参数,并且返回库加载器所指定的默认结果类型。 它们是一个私有类的实例:

class ctypes._FuncPtr¶

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

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

此行为可通过对外部函数对象的特殊属性赋值来自定义。

restype¶

赋值为一个 ctypes 类型来指定外部函数的结果类型。 使用 None 表示 void,即不返回任何结果的函数。

赋值为一个不为 ctypes 类型的可调用 Python 对象也是可以的,在此情况下函数应返回 C int,该可调用对象将附带此整数被调用,以允许进一步的处理或错误检测。 这种用法已被弃用,为了更灵活的后续处理或错误检测请使用一个 ctypes 数据类型作为 restype 并将 errcheck 属性赋值为一个可调用对象。

argtypes¶

赋值为一个 ctypes 类型的元组来指定函数所接受的参数类型。 使用 stdcall 调用规范的函数只能附带与此元组长度相同数量的参数进行调用;使用 C 调用规范的函数还可接受额外的未指明参数。

当外部函数被调用时,每个实际参数都会被传给 argtypes 元组中条目的 from_param() 类方法,此方法允许将实际参数适配为此外部函数所接受的对象。 例如,argtypes 元组中的 c_char_p 条目将使用 ctypes 约定规则把作为参数传入的字符串转换为字节串对象。

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

errcheck¶

将一个 Python 函数或其他可调用对象赋值给此属性。 该可调用对象将附带三个及以上的参数被调用。

callable(result, func, arguments)

result 是外部函数返回的结果,由 restype 属性指明。

func 是外部函数对象本身,这样就允许重新使用相同的可调用对象来对多个函数进行检查或后续处理。

arguments 是一个包含最初传递给函数调用的形参的元组,这样就允许对所用参数的行为进行特别处理。

此函数所返回的对象将会由外部函数调用返回,但它还可以在外部函数调用失败时检查结果并引发异常。

exception ctypes.ArgumentError¶

此异常会在外部函数无法对某个传入参数执行转换时被引发。

函数原型¶

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

ctypes.CFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)¶

返回的函数原型会创建使用标准 C 调用约定的函数。 该函数在调用过程中将释放 GIL。 如果 use_errno 设为真值,则在调用之前和之后系统 errno 变量的 ctypes 私有副本会与真正的 errno 值进行交换;use_last_error 会为 Windows 错误码执行同样的操作。

ctypes.WINFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)¶

仅限 Windows only:返回的函数原型会创建使用 stdcall 调用约定的函数,但在 Windows CE 上 WINFUNCTYPE() 则会与 CFUNCTYPE() 相同。 该函数在调用过程中将释放 GIL。 use_errno 和 use_last_error 具有与前面相同的含义。

ctypes.PYFUNCTYPE(restype, *argtypes)¶

返回的函数原型会创建使用 Python 调用约定的函数。 该函数在调用过程中将 不会 释放 GIL。

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

prototype(address)

在指定地址上返回一个外部函数,地址值必须为整数。

prototype(callable)

基于 Python callable 创建一个 C 可调用函数(回调函数)。

prototype(func_spec[, paramflags])

返回由一个共享库导出的外部函数。 func_spec 必须为一个 2 元组 (name_or_ordinal, library)。 第一项是字符串形式的所导出函数名称,或小整数形式的所导出函数序号。 第二项是该共享库实例。

prototype(vtbl_index, name[, paramflags[, iid]])

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

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

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

paramflags 必须为一个与 argtypes 长度相同的元组。

此元组中的每一项都包含有关形参的更多信息,它必须为包含一个、两个或更多条目的元组。

第一项是包含形参指令旗标组合的整数。

1

指定函数的一个输入形参。

2

输出形参。 外部函数会填入一个值。

4

默认为整数零值的输入形参。

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

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

这个例子演示了如何包装 Windows 的 MessageBoxW 函数以使其支持默认形参和已命名参数。 相应 windows 头文件的 C 声明是这样的:

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

这是使用 ctypes 的包装:

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

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

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

第二个例子演示了输出形参。 这个 win32 GetWindowRect 函数通过将指定窗口的维度拷贝至调用者必须提供的 RECT 结构体来提取这些值。 这是相应的 C 声明:

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

这是使用 ctypes 的包装:

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

带有输出形参的函数如果输出形参存在单一值则会自动返回该值,或是当输出形参存在多个值时返回包含这些值的元组,因此当 GetWindowRect 被调用时现在将返回一个 RECT 实例。

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

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

如果 errcheck 不加更改地返回它所接收的参数元组,则 ctypes 会继续对输出形参执行常规处理。 如果你希望返回一个窗口坐标的元组而非 RECT 实例,你可以从函数中提取这些字段并返回它们,常规处理将不会再执行:

>>> def errcheck(result, func, args): ... if not result: ... raise WinError() ... rc = args[1] ... return rc.left, rc.top, rc.bottom, rc.right ... >>> GetWindowRect.errcheck = errcheck >>> 工具函数¶ ctypes.addressof(obj)¶

以整数形式返回内存缓冲区地址。 obj 必须为一个 ctypes 类型的实例。

ctypes.alignment(obj_or_type)¶

返回一个 ctypes 类型的对齐要求。 obj_or_type 必须为一个 ctypes 类型或实例。

ctypes.byref(obj[, offset])¶

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

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

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

返回的对象只能被用作外部函数调用形参。 它的行为类似于 pointer(obj),但构造起来要快很多。

ctypes.cast(obj, type)¶

此函数类似于 C 的强制转换运算符。 它返回一个 type 的新实例,该实例指向与 obj 相同的内存块。 type 必须为指针类型,而 obj 必须为可以被作为指针来解读的对象。

ctypes.create_string_buffer(init_or_size, size=None)¶

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

init_or_size 必须是一个指明数组大小的整数,或者是一个将被用来初始化数组条目的字节串对象。

如果将一个字节串对象指定为第一个参数,则将使缓冲区大小比其长度多一项以便数组的最后一项为一个 NUL 终结符。 可以传入一个整数作为第二个参数以允许在不使用字节串长度的情况下指定数组大小。

ctypes.create_unicode_buffer(init_or_size, size=None)¶

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

init_or_size 必须是一个指明数组大小的整数,或者是一个将被用来初始化数组条目的字符串。

如果将一个字符串指定为第一个参数,则将使缓冲区大小比其长度多一项以便数组的最后一项为一个 NUL 终结符。 可以传入一个整数作为第二个参数以允许在不使用字符串长度的情况下指定数组大小。

ctypes.DllCanUnloadNow()¶

仅限 Windows:此函数是一个允许使用 ctypes 实现进程内 COM 服务的钩子。 它将由 _ctypes 扩展 dll 所导出的 DllCanUnloadNow 函数来调用。

ctypes.DllGetClassObject()¶

仅限 Windows:此函数是一个允许使用 ctypes 实现进程内 COM 服务的钩子。 它将由 _ctypes 扩展 dll 所导出的 DllGetClassObject 函数来调用。

ctypes.util.find_library(name)¶

尝试寻找一个库并返回路径名称。 name 是库名称并且不带任何前缀如 lib 以及后缀如 .so,.dylib 或版本号(形式与 posix 链接器选项 -l 所用的一致)。 如果找不到库,则返回 None。

确切的功能取决于系统。

ctypes.util.find_msvcrt()¶

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

如果你需要通过调用 free(void *) 来释放内存,例如某个扩展模块所分配的内存,重要的一点是你应当使用分配内存的库中的函数。

ctypes.FormatError([code])¶

仅限 Windows:返回错误码 code 的文本描述。 如果未指定错误码,则会通过调用 the last error code is used by calling the Windows api 函数 GetLastError 来获得最新的错误码。

ctypes.GetLastError()¶

仅限 Windows:返回 Windows 在调用线程中设置的最新错误码。 此函数会直接调用 Windows GetLastError() 函数,它并不返回错误码的 ctypes 私有副本。

ctypes.get_errno()¶

返回调用线程中系统 errno 变量的 ctypes 私有副本的当前值。

ctypes.get_last_error()¶

仅限 Windows:返回调用线程中系统 LastError 变量的 ctypes 私有副本的当前值。

ctypes.memmove(dst, src, count)¶

与标准 C memmove 库函数相同:将 count 个字节从 src 拷贝到 dst。 dst 和 src 必须为整数或可被转换为指针的 ctypes 实例。

ctypes.memset(dst, c, count)¶

与标准 C memset 库函数相同:将位于地址 dst 的内存块用 count 个字节的 c 值填充。 dst 必须为指定地址的整数或 ctypes 实例。

ctypes.POINTER(type)¶

这个工厂函数创建并返回一个新的 ctypes 指针类型。 指针类型会被缓存并在内部重用,因此重复调用此函数耗费不大。 type 必须为 ctypes 类型。

ctypes.pointer(obj)¶

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

注意:如果你只是想向外部函数调用传递一个对象指针,你应当使用更为快速的 byref(obj)。

ctypes.resize(obj, size)¶

此函数可改变 obj 的内部内存缓冲区大小,其参数必须为 ctypes 类型的实例。 没有可能将缓冲区设为小于对象类型的本机大小值,该值由 sizeof(type(obj)) 给出,但将缓冲区加大则是可能的。

ctypes.set_errno(value)¶

设置调用线程中系统 errno 变量的 ctypes 私有副本的当前值为 value 并返回原来的值。

ctypes.set_last_error(value)¶

仅限 Windows:设置调用线程中系统 LastError 变量的 ctypes 私有副本的当前值为 value 并返回原来的值。

ctypes.sizeof(obj_or_type)¶

返回 ctypes 类型或实例的内存缓冲区以字节表示的大小。 其功能与 C sizeof 运算符相同。

ctypes.string_at(address, size=-1)¶

此函数返回从内存地址 address 开始的以字节串表示的 C 字符串。 如果指定了 size,则将其用作长度,否则将假定字符串以零值结尾。

ctypes.WinError(code=None, descr=None)¶

仅限 Windows:此函数可能是 ctypes 中名字起得最差的函数。 它会创建一个 OSError 的实例。 如果未指定 code,则会调用 GetLastError 来确定错误码。 如果未指定 descr,则会调用 FormatError() 来获取错误的文本描述。

在 3.3 版更改: 以前是会创建一个 WindowsError 的实例。

ctypes.wstring_at(address, size=-1)¶

此函数返回从内存地址 address 开始的以字符串表示的宽字节字符串。 如果指定了 size,则将其用作字符串中的字符数量,否则将假定字符串以零值结尾。

数据类型¶ class ctypes._CData¶

这个非公有类是所有 ctypes 数据类型的共同基类。 另外,所有 ctypes 类型的实例都包含一个存放 C 兼容数据的内存块;该内存块的地址可由 addressof() 辅助函数返回。 还有一个实例变量被公开为 _objects;此变量包含其他在内存块包含指针的情况下需要保持存活的 Python 对象。

ctypes 数据类型的通用方法,它们都是类方法(严谨地说,它们是 metaclass 的方法):

from_buffer(source[, offset])¶

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

from_buffer_copy(source[, offset])¶

此方法创建一个 ctypes 实例,从 source 对象缓冲区拷贝缓冲区,该对象必须是可读的。 可选的 offset 形参指定以字节表示的源缓冲区内偏移量;默认值为零。 如果源缓冲区不够大则会引发 ValueError。

from_address(address)¶

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

from_param(obj)¶

此方法会将 obj 适配为一个 ctypes 类型。 它调用时会在当该类型存在于外部函数的 argtypes 元组时传入外部函数调用所使用的实际对象;它必须返回一个可被用作函数调用参数的对象。

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

in_dll(library, name)¶

此方法返回一个由共享库导出的 ctypes 类型。 name 为导出数据的符号名称,library 为所加载的共享库。

ctypes 数据类型的通用实例变量:

_b_base_¶

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

_b_needsfree_¶

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

_objects¶

这个成员或者为 None,或者为一个包含需要保持存活以使内存块的内存保持有效的 Python 对象的字典。 这个对象只是出于调试目的而对外公开;绝对不要修改此字典的内容。

基础数据类型¶ class ctypes._SimpleCData¶

这个非公有类是所有基本 ctypes 数据类型的基类。 它在这里被提及是因为它包含基本 ctypes 数据类型共有的属性。 _SimpleCData 是 _CData 的子类,因此继承了其方法和属性。 非指针及不包含指针的 ctypes 数据类型现在将可以被封存。

实例拥有一个属性:

value¶

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

当从 ctypes 实例提取 value 属性时,通常每次会返回一个新的对象。 ctypes 并 没有 实现原始对象返回,它总是会构造一个新的对象。 所有其他 ctypes 对象实例也同样如此。

基本数据类型当作为外部函数调用结果被返回或者作为结构字段成员或数组项被提取时,会透明地转换为原生 Python 类型。 换句话说,如果某个外部函数具有 c_char_p 的 restype,你将总是得到一个 Python 字节串对象,而 不是 一个 c_char_p 实例。

基本数据类型的子类并 没有 继续此行为。 因此,如果一个外部函数的 restype 是 c_void_p 的一个子类,你将从函数调用得到一个该子类的实例。 当然,你可以通过访问 value 属性来获取指针的值。

这些是基本 ctypes 数据类型:

class ctypes.c_byte¶

代表 C signed char 数据类型,并将值解读为一个小整数。 该构造器接受一个可选的整数初始化器;不会执行溢出检查。

class ctypes.c_char¶

代表 C char 数据类型,并将值解读为单个字符。 该构造器接受一个可选的字符串初始化器,字符串的长度必须恰好为一个字符。

class ctypes.c_char_p¶

当指向一个以零为结束符的字符串时代表 C char * 数据类型。 对于通用字符指针来说也可能指向二进制数据,必须要使用 POINTER(c_char)。 该构造器接受一个整数地址,或者一个字节串对象。

class ctypes.c_double¶

代表 C double 数据类型。 该构造器接受一个可选的浮点数初始化器。

class ctypes.c_longdouble¶

代表 C long double 数据类型。 该构造器接受一个可选的浮点数初始化器。 在 sizeof(long double) == sizeof(double) 的平台上它是 c_double 的一个别名。

class ctypes.c_float¶

代表 C float 数据类型。 该构造器接受一个可选的浮点数初始化器。

class ctypes.c_int¶

代表 C signed int 数据类型。 该构造器接受一个可选的整数初始化器;不会执行溢出检查。 在 sizeof(int) == sizeof(long) 的平台上它是 c_long 的一个别名。

class ctypes.c_int8¶

代表 C 8 位 signed int 数据类型。 通常是 c_byte 的一个别名。

class ctypes.c_int16¶

代表 C 16 位 signed int 数据类型。 通常是 c_short 的一个别名。

class ctypes.c_int32¶

代表 C 32 位 signed int 数据类型。 通常是 c_int 的一个别名。

class ctypes.c_int64¶

代表 C 64 位 signed int 数据类型。 通常是 c_longlong 的一个别名。

class ctypes.c_long¶

代表 C signed long 数据类型。 该构造器接受一个可选的整数初始化器;不会执行溢出检查。

class ctypes.c_longlong¶

代表 C signed long long 数据类型。 该构造器接受一个可选的整数初始化器;不会执行溢出检查。

class ctypes.c_short¶

代表 C signed short 数据类型。 该构造器接受一个可选的整数初始化器;不会执行溢出检查。

class ctypes.c_size_t¶

代表 C size_t 数据类型。

class ctypes.c_ssize_t¶

代表 C ssize_t 数据类型。

3.2 新版功能.

class ctypes.c_ubyte¶

代表 C unsigned char 数据类型,它将值解读为一个小整数。 该构造器接受一个可选的整数初始化器;不会执行溢出检查。

class ctypes.c_uint¶

代表 C unsigned int 数据类型。 该构造器接受一个可选的整数初始化器;不会执行溢出检查。 在 sizeof(int) == sizeof(long) 的平台上它是 c_ulong 的一个别名。

class ctypes.c_uint8¶

代表 C 8 位 unsigned int 数据类型。 通常是 c_ubyte 的一个别名。

class ctypes.c_uint16¶

代表 C 16 位 unsigned int 数据类型。 通常是 c_ushort 的一个别名。

class ctypes.c_uint32¶

代表 C 32 位 unsigned int 数据类型。 通常是 c_uint 的一个别名。.

class ctypes.c_uint64¶

代表 C 64 位 unsigned int 数据类型。 通常是 c_ulonglong 的一个别名。

class ctypes.c_ulong¶

代表 C unsigned long 数据类型。 该构造器接受一个可选的整数初始化器;不会执行溢出检查。

class ctypes.c_ulonglong¶

代表 C unsigned long long 数据类型。 该构造器接受一个可选的整数初始化器;不会执行溢出检查。

class ctypes.c_ushort¶

代表 C unsigned short 数据类型。 该构造器接受一个可选的整数初始化器;不会执行溢出检查。

class ctypes.c_void_p¶

代表 C void * 类型。 该值被表示为整数形式。 该构造器接受一个可选的整数初始化器。

class ctypes.c_wchar¶

代表 C wchar_t 数据类型,并将值解读为一单个字符的 unicode 字符串。 该构造器接受一个可选的字符串初始化器,字符串的长度必须恰好为一个字符。

class ctypes.c_wchar_p¶

代表 C wchar_t * 数据类型,它必须为指向以零为结束符的宽字符串的指针。 该构造器接受一个整数地址或者一个字符串。

class ctypes.c_bool¶

代表 C bool 数据类型 (更准确地说是 C99 _Bool)。 它的值可以为 True 或 False,并且该构造器接受任何具有逻辑值的对象。

class ctypes.HRESULT¶

Windows 专属:代表一个 HRESULT 值,它包含某个函数或方法调用的成功或错误信息。

class ctypes.py_object¶

代表 C PyObject * 数据类型。 不带参数地调用此构造器将创建一个 NULL PyObject * 指针。

ctypes.wintypes 模块提供了其他许多 Windows 专属的数据类型,例如 HWND, WPARAM 或 DWORD。 还定义了一些有用的结构体例如 MSG 或 RECT。

结构化数据类型¶ class ctypes.Union(*args, **kw)¶

本机字节序的联合所对应的抽象基类。

class ctypes.BigEndianStructure(*args, **kw)¶

大端 字节序的结构体所对应的抽象基类。

class ctypes.LittleEndianStructure(*args, **kw)¶

小端 字节序的结构体所对应的抽象基类。

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

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

本机 字节序的结构体所对应的抽象基类。

实际的结构体和联合类型必须通过子类化这些类型之一来创建,并且至少要定义一个 _fields_ 类变量。 ctypes 将创建 descriptor,它允许通过直接属性访问来读取和写入字段。 这些是

_fields_¶

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

对于整数类型字段例如 c_int,可以给定第三个可选项。 它必须是一个定义字段比特位宽度的小正整数。

字段名称在一个结构体或联合中必须唯一。 不会检查这个唯一性,但当名称出现重复时将只有一个字段可被访问。

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

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

但是,_fields_ 类变量必须在类型第一次被使用(创建实例,调用 sizeof() 等等)之前进行定义。 在此之后对 _fields_ 类变量赋值将会引发 AttributeError。

可以定义结构体类型的子类,它们会继承基类的字段再加上在子类中定义的任何 _fields_。

_pack_¶

一个可选的小整数,它允许覆盖实体中结构体字段的对齐方式。 当 _fields_ 被赋值时必须已经定义了 _pack_,否则它将没有效果。

_anonymous_¶

一个可选的序列,它会列出未命名(匿名)字段的名称。 当 _fields_ 被赋值时必须已经定义了 _anonymous_,否则它将没有效果。

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

以下是一个示例类型(Windows):

class _U(Union): _fields_ = [("lptdesc", POINTER(TYPEDESC)), ("lpadesc", POINTER(ARRAYDESC)), ("hreftype", HREFTYPE)] class TYPEDESC(Structure): _anonymous_ = ("u",) _fields_ = [("u", _U), ("vt", VARTYPE)]

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

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

可以定义结构体的子类,它们会继承基类的字段。 如果子类定义具有单独的 _fields_ 变量,在其中指定的字段会被添加到基类的字段中。

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

数组与指针¶ class ctypes.Array(*args)¶

数组的抽象基类。

创建实际数组类型的推荐方式是通过将任意 ctypes 类型与一个正整数相乘。 作为替代方式,你也可以子类化这个类型并定义 _length_ 和 _type_ 类变量。 数组元素可使用标准的抽取和切片方式来读写;对于切片读取,结果对象本身 并非 一个 Array。

_length_¶

一个指明数组中元素数量的正整数。 超出范围的抽取会导致 IndexError。 该值将由 len() 返回。

_type_¶

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

Array 子类构造器可接受位置参数,用来按顺序初始化元素。

class ctypes._Pointer¶

私有对象,指针的抽象基类。

实际的指针类型是通过调用 POINTER() 并附带其将指向的类型来创建的;这会由 pointer() 自动完成。

如果一个指针指向的是数组,则其元素可使用标准的抽取和切片方式来读写。 指针对象没有长度,因此 len() 将引发 TypeError。 抽取负值将会从指针 之前 的内存中读取(与 C 一样),并且超出范围的抽取将可能因非法访问而导致崩溃(视你的运气而定)。

_type_¶

指明所指向的类型。

contents¶

返回指针所指向的对象。 对此属性赋值会使指针改为指向所赋值的对象。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3