ctypes
简介#
参考资料:
ctypes
是 Python 的外部函数库。它提供了与 C 兼容的数据类型,并允许调用 DLL 或共享库中的函数。可使用该模块以纯 Python 形式对这些库进行封装。
备注
加载动态链接库#
ctypes
导出了 cdll
对象,在 Windows 系统中还导出了 windll
和 oledll
对象用于载入动态连接库。
您可以通过访问这些对象的属性来加载库。
cdll
加载使用标准cdecl
调用约定导出函数的库而
windll
库则使用stdcall
调用约定调用函数oledll
也使用stdcall
调用约定,并假定函数返回 Windows HRESULT 错误代码。
当函数调用失败时会使用错误代码自动引发 OSError
异常。
备注
cdecl
和 stdcall
是两种不同的函数调用约定,它们定义了函数参数的传递方式、堆栈清理责任以及名称修饰规则。
cdecl(C declaration):
参数传递顺序是从右到左,即最右边的参数最先入栈。
调用者负责清理堆栈(即由函数外部的代码来恢复堆栈指针)。
支持变长参数列表,因此常用于具有可变数量参数的函数,如printf。
在函数名前加上一个下划线作为前缀进行名称修饰(仅在编译时)。
stdcall(Standard call):
参数传递顺序也是从右到左。
被调用的函数负责清理堆栈(即由函数内部的代码来恢复堆栈指针)。
不支持变长参数列表。
在函数名前加上一个下划线作为前缀,并在其后添加一个表示参数字节数的后缀进行名称修饰(仅在编译时)。
两者的联系在于它们都是x86架构上常见的函数调用约定,主要用于Windows平台的软件开发。选择使用哪种调用约定通常取决于特定的编程环境和需求。例如,如果你需要与Windows API进行交互,可能会更倾向于使用stdcall
,因为这是Windows API主要使用的调用约定。而cdecl
则更常见于GCC编译器中,特别是在UNIX或Linux平台上。
请注意,msvcrt
是包含大多数标准 C 函数的 MS 标准 C 库,并使用 cdecl
调用约定:
>>> from ctypes import *
>>> print(windll.kernel32)
<WinDLL 'kernel32', handle ... at ...>
>>> print(cdll.msvcrt)
<CDLL 'msvcrt', handle ... at ...>
>>> libc = cdll.msvcrt
Windows 会自动添加通常的 .dll
文件扩展名。
备注
通过 cdll.msvcrt
调用的标准 C 函数,可能会导致调用一个过时的,与当前 Python 所不兼容的函数。因此,请尽量使用标准的 Python 函数,而不要使用 msvcrt
模块。
在 Linux 中,要求指定文件名 包括 扩展名来加载库,因此不能使用属性访问的方式来加载库。你应当使用 dll
加载器的 LoadLibrary()
方法,或是应当通过调用构造器创建 CDLL
的实例来加载库:
>>> cdll.LoadLibrary("libc.so.6")
<CDLL 'libc.so.6', handle ... at ...>
>>> libc = CDLL("libc.so.6")
>>> libc
<CDLL 'libc.so.6', handle ... at ...>