没有合适的资源?快使用搜索试试~ 我知道了~
python-ctypes模块中文帮助文档.pdf
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 19 浏览量
2021-11-25
10:12:28
上传
评论
收藏 43KB PDF 举报
温馨提示
试读
23页
python-ctypes模块中文帮助文档.pdf
资源推荐
资源详情
资源评论
内容:
.加载动态链接库
.从已加载的 dll 中引用函数
.调用函数 1
.基本的数据类型
.调用函数 2
.用自己的数据类型调用函数
.确认需要的参数类型(函数原型)
.返回值
.传递指针
.结构和联合
.结构或联合的对齐方式和字节的顺序
.结构和联合中的位
.数组
.指针
.类型转换
.未完成的类型
.回调函数
.访问 dlls 导出的值
.可变长度的数据类型
.bugs 将要做的和没有做的事情
注意:本文中的代码例子使用 doctest 确保他们能够实际工作。一些代码例子在 linux 和
windows 以及苹果机上执行有一定的差别
注意:一些代码引用了 ctypes 的 c_int 类型。它是 c_long 在 32 位机子上的别名,你不应该
变得迷惑,如果你期望
的是 c_int 类型,实事上打印的是 c_long,它们实事上是相同的类型。
加载动态链接库
ctypes 加载动态链接库,导出 cdll 和在 windows 上同样也导出 windll 和 oledll 对象。
加载动态链接库后,你可以像使用对象的属性一样使用它们。 cdll 加载使用标准的 cdecl 调
用约定的链接库,
而 windll 库使用 stdcall 调用约定, oledll 也使用 stdcall 调用约定,同时确保函数返回一个
windows HRESULT错误代码。这错误
代码自动的升为 WindowsError Python exceptions ,当这些函数调用失败时。
这有一些 windows 例子, msvcrt 是微软的 c 标准库,包含大部分的标准 c 函数,同时使用
cdecl 调用约定。
注: cdecl 和 stdcall 的区别请见 http://butlandblog.appspot.com/log-20.html
>>> from ctypes import *
>>> print windll.kernel32 # doctest: +WINDOWS
<WinDLL 'kernel32', handle ... at ...>
>>> print cdll.msvcrt # doctest: +WINDOWS
<CDLL 'msvcrt', handle ... at ...>
>>> libc = cdll.msvcrt # doctest: +WINDOWS
>>>
windows 自动添加常用的 .dll 文件后缀名
在 linux 上,需要使用包含扩展名的文件名来加载一个库, 因此属性操作不能正常使用。 或
者使用 dll 加载器的
LoadLibrary 方法,或者通过 CDLL构造函数创建一个 CDLL的一个实例
>>> cdll.LoadLibrary("libc.so.6") # doctest: +LINUX
<CDLL 'libc.so.6', handle ... at ...>
>>> libc = CDLL("libc.so.6") # doctest: +LINUX
>>> libc # doctest: +LINUX
<CDLL 'libc.so.6', handle ... at ...>
>>>
加载 dll 使用其中函数
使用函数就像对象的属性
>>> from ctypes import *
>>> libc.printf
<_FuncPtr object at 0x...>
>>> print windll.kernel32.GetModuleHandleA # doctest: +WINDOWS
<_FuncPtr object at 0x...>
>>> print windll.kernel32.MyOwnFunction # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "ctypes.py", line 239, in __getattr__
func = _StdcallFuncPtr(name, self)
AttributeError: function 'MyOwnFunction' not found
>>>00
注意 win32 系统 dll 像 kernel32 和 user32 大部分导出 ANSI 和 UNICODE版本函数, UNICODE
版本以一个 W 结尾导出
而 ANSI版本则以一个 A 结尾导出的。 win32 GetModuleHandle 函数,返回一个指定的 module
名字的 module 句柄
下面 c 原型, GetModuleHandle 的 macro,依赖于它是不是 UNICODE。
/* ANSI version */
HMODULE GetModuleHandleA(LPCSTR lpModuleName);
/* UNICODE version */
HMODULE GetModuleHandleW(LPCWSTR lpModuleName);
windll 不 会 神 奇 的 自 已 去 选 择 一 个 , 你 必 须 显 式 确 认 GetModuleHandleA 或 者
GetModuleHandleW 去使用它们
去处理一般字符串或 unicode 字符串。
有时候, dll 导出函数名, python 无法识别 ,像"??2@YAPAXI@Z". 在这情况下,你必须使用
getattr 去使用这些函数
>>> getattr(cdll.msvcrt, "??2@YAPAXI@Z") # doctest: +WINDOWS
<_FuncPtr object at 0x...>
>>>
在 windows 上,一些 dllS 不是导出函数名,而是以顺序,这些函数可以将这些数字当作 dll
对象的索引来使用
这些函数。
>>> cdll.kernel32[1] # doctest: +WINDOWS
<_FuncPtr object at 0x...>
>>> cdll.kernel32[0] # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "ctypes.py", line 310, in __getitem__
func = _StdcallFuncPtr(name, self)
AttributeError: function ordinal 0 not found
>>>
调用函数
你可调用这些函数,像其它的 python 函数一样,下面的例子使用 time() 函数,它以秒为单
位返回从 unix 新纪元的系统时间
,GetModuleHandleA() 函数,返回一个 win32 模块句柄。
下面的例子用空指针调用函数( None 作为空指针)
>>> print libc.time(None) # doctest: +SKIP
1150640792
>>> print hex(windll.kernel32.GetModuleHandleA(None)) # doctest: +WINDOWS
0x1d000000
>>>
ctypes 尝试阻止你以错误的参数数量或调用约定来调用函数。不幸的是,这些仅仅能在
windows 上工作
它在函数返回后不会去检查这栈,尽管在调用函数后有错误发生。
>>> windll.kernel32.GetModuleHandleA() # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
>>> windll.kernel32.GetModuleHandleA(0, 0) # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
>>>
产生了同样的 exception ,当你用 cdecl 调用约定去使用一个 stdcall 函数,反之亦然。
>>> cdll.kernel32.GetModuleHandleA(None) # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
>>>
>>> windll.msvcrt.printf("spam") # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
>>>
找到正确的调用约定,你必须检查 c 头文件或者你想调用的函数的文档。
在 windows ,ctypes 使用 win32 结构 exception 处理一般的保护错误阻止 crashes,当调用无
效的参数值
>>> windll.kernel32.GetModuleHandleA(32) # doctest: +WINDOWS
Traceback (most recent call last):
File "<stdin>", line 1, in ?
WindowsError: exception: access violation reading 0x00000020
>>>
然而有很多种可能性会发生 crash,你使用 python 的 ctypes,你应该足够的小心。
None,integers,longs,byte strings 和 unicode string 是 python 内置对象,可以直接的作为这些
函数的参数
,None 作为一个空指针, byte string 和 unicode string 当作一个内存块, 它包含这些数据 (char*
或者 wchar_t* )
。python 的 int 和 long 长整形作为 c int 类型 ,它们的值对应着 c 类型。
在调用带有参数的函数之前,我们必须学习更多的关于 ctypes 数据类型。
基础的数据类型
ctypes 定义了许多主要的 c 兼容有数据类型
数据类型请见 http://butlandblog.appspot.com/log-21.html
使用它们和一个可选的正确的值去创建所有的这些类型
>>> c_int()
c_long(0)
>>> c_char_p("Hello, World")
c_char_p('Hello, World')
>>> c_ushort(-3)
c_ushort(65533)
>>>
因此这些类型是可变的,他们的值在后面也是可以改变的
分配一个新值到这些指针类型 c_char_p, c_wchar_p, 和 c_void_p 的一个实例上, 改变它们指
向的
内存位置,而不是这些内存块的内容(当然,因为 python 的 string 是不可改变的)
>>> s = "Hello, World"
>>> c_s = c_char_p(s)
>>> print c_s
c_char_p('Hello, World')
>>> c_s.value = "Hi, there"
>>> print c_s
c_char_p('Hi, there')
>>> print s # first string is unchanged
Hello, World
>>>
你应该注意,不要期望传给函数指针是指向可变的内存。如果你需要可变的内存块, ctypes
有一个
create_string_buffer 函数。 这内存块内容通过这 raw 属性来访问或改变, 如果你想访问一个
以 null 结束
的字符串,使用这 string 属性
>>> from ctypes import *
>>> p = create_string_buffer(3) # create a 3 byte buffer, initialized to NUL bytes
>>> print sizeof(p), repr(p.raw)
剩余22页未读,继续阅读
资源评论
zhaomu321
- 粉丝: 0
- 资源: 3万+
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功