Python中的Ctypes

ctypes是Python中的一个标准库,它提供了一种Python调用C语言动态连接库的方法,可以将C语言的库文件方便的加上一个pyhton的调用接口。

指定连接库文件

在不同平台上ctypes导入的文件是不同的,一般linux上是cdll,windows上是windlloledll

cdll的导入方式用的是cdecl的调用方式,而windll的调用方式是stdcalloledall用的也是stdcall,不过它的前提是函数会返回windows格式的HRESULT的错误码。

下面是导入windows标准库msvcrt的一个实现:

from ctypes import *
print(windll.kernel32)
>> ....
print(cdll.msvcrt)
>> ....
libc = cdll.msvcrt

在linux上,导入库的时候需要指定文件名和文件后缀,并且不支持通过属性的方式加载库,一般需要通过cdll.LoadLibrary或者CDLL的方式导入。

cdll.LoadLibrary("libc.so.6")
# or
libc = CDLL("libc.so.6")

调用库中的函数

在加载完库之后,库中的函数就可以像一般的属性去访问。

from ctypes import *
libc.printf
>> <_FuncPtr....
libc.time(None)
>>> 115....

需要注意的是stdcallcdecl的调用是有区别的,如果用cdecl的方式调用一个stdcall的函数会触发一个ValueError的错误,反之亦然。

在进行函数调用的时候python会自动去尝试从python类型到c语言类型的转换,如果转换失败就会出现ArgumentError,比如

printf = libc.printf
# OK, string converted
printf(b"Hello %s", b"world")
printf(b"Hello %s", "world")
# FAIL float not converted
printf(b"price is %f", 42.5)
# OK add conversion
printf(b"price is %f", c_double(42.5))

如果需要传入一些自定义的类作为参数,可以定义一个_as_parameter_的方法,这样将类作为参数的时候python会自动进行转换。

数组

为了方便产生数组,ctypes类型重载了操作符*,因此可以通过下面的方式产生一个指定长度的数组:

from ctypes import *

# 创建一个数组类型
type_int_array_10 = c_int * 10
# 例化创建的数组类型,得到一个数组的实例
my_array = type_int_array_10()

发表新评论