python调用ctypes中windll中的方法超时处理_python通过ctypes调用dll

本文介绍了如何在Python中使用ctypes库调用C语言的DLL动态链接库,包括stdcal和cdecl两种调用规则,以及参数传递、返回值类型、数组、结构、指针等复杂数据类型的处理。还提到了如何处理调用超时问题以及使用默认加载的库如msvcrt、kernel32和user32。
摘要由CSDN通过智能技术生成

ctypes库简介

python调用c等语言的方法很多如,python c api, boost.python, Swig 等等。ctypes库可以通过一种较为简单的方法,在python中直接调用dll动态链接库,且ctypes是python默认已安装的一个标准库。

调用方法

python中如果要通过ctypes模块调用dll,在程序开头需要导入ctypes模块 import ctypes

由于调用约定的不同,python调用dll的方法也不同,主要有两种调用规则,即 cdecl和stdcal,还有其他的一些调用约定,关于他们的不同,可以查阅其他资料

假定有一个test.dll文件,含有int sum(int a, int b)函数,则调用方法为:

stdcal的调用方法

import ctypes

dll=ctypes.windll.LoadLibrary('test.dll')

n=dll.sum(1,2)

import ctypes

dll=ctypes.WinDll('test.dll')

n=dll.sum(1,2)

from cypes import *

dll=WinDll('test.dll')

sum=dll.sum

n=sum(1,2)

其中ctypes.windll为ctypes.WinDll类的一个对象,已经在ctypes模块中定义好的。

在linux中用相同的方法,只需把dll文件换成so文件

在windows下加载so文件或在linux下加载dll文件均无法运行

cdecl的调用方法

与stdcal调用方式相似

from ctypes import *

dll=CDll('test.dll')

n=dll.sum(1,2)

python与dll参数传递

python中仅有4个类型可以直接传递给dll函数

None:C语言的NULL指针

byte objects:ANSI字符串(char *)

string:unicode字符串(wchar_t *)

integer:C语言整形(int)

传递其他类型参数给dll函数,必须使用ctypes 数据类型

ctypes基础数据类型

ctypes定义了一系列类型用于兼容c数据类型,这些类型以c_开头

ctypes type

C type

Python type

c_bool

_Bool

bool (1)

c_char

char

1-character bytes object

c_wchar

wchar_t

1-character string

c_byte

char

int

c_ubyte

unsigned

char int

c_short

short

int

c_ushort

unsigned short

int

c_int

int

int

c_uint

unsigned int

int

c_long

long

int

c_ulong

unsigned long

int

c_longlong

__int64 or long long

int

c_ulonglong

unsigned __int64 or unsigned long long

int

c_size_t

size_t

int

c_ssize_t

ssize_t or Py_ssize_t

int

c_float

float

float

c_double

double

float

c_longdouble

long double

float

c_char_p

char * (NUL terminated)

bytes object or None

c_wchar_p

wchar_t * (NUL terminated)

string or None

c_void_p

void *

int or None

可以通过value属性修改ctypes类型数据的值

from ctypes import *

i=c_int(42)

i.value=40

c=c_char(b"x")

c.value=b"y"

s=c_wchar_p("hello")

s.value="hi"

f=c_double(4.3)

c_char_p和c_wchar_p是字符串指针,在改变value值时,相当于指向另一个地址,原字符串长度是不可变的,可变长度字符串需要用到create_string_buffer()或create_unicode_buffer()

from ctypes import *

p=create_string_buffer(b"hello")

p.value=b"hi"

ctypes复杂数据类型

数组

n=10

a=(c_double*n)()

a[0]=1

结构

from ctypes import *

class POINT(Structure):

_fields_=[("x",c_int),

("y",c_int)]

pt1=POINT(10,20)

引用

用byref()函数可以实现传递引用参数

>>> i = c_int()

>>> f = c_float()

>>> s = create_string_buffer(b'\000' * 32)

>>> print(i.value, f.value, repr(s.value))

0 0.0 b''

>>> libc.sscanf(b"1 3.14 Hello", b"%d %f %s",

... byref(i), byref(f), s)

3

>>> print(i.value, f.value, repr(s.value))

1 3.1400001049 b'Hello'

指针

指针也可以实现传递应用类型,但是指针比byref()功能更多,ctypes的Pointer()类型还可以在python中像数组一样访问

用contents属性可以访问指针内容

>>> from ctypes import *

>>> i=c_int(42)

>>> pi=pointer(i)

>>> pi.contents

c_long(42)

>>> j=c_int(99)

>>> pi.contents=j

>>> pi[0]

99

python调用dll返回值类型

python通过ctypes调用的dll函数返回值,被默认假定为

integer

如果返回值是其他类型,必须通过restype属性指定

>>> strchr = libc.strchr

>>> strchr(b"abcdef", ord("d"))

8059983

>>> strchr.restype = c_char_p

>>> strchr(b"abcdef", ord("d"))

b'def'

python默认已加载库

kernel32, user32, msvcrt是python默认已加载的库,可以通过cdll.msvcrt.printf(), windll.kernel32.GetMessageBoxW()形式调用

msvcrt是ms标准c库函数

kernel32, user32内函数需要指明是A版(ANSI字符)还是W版(Unicode字符)windows接口。

GetSystemDirectory = windll.kernel32.GetSystemDirectoryA

buf = create_string_buffer(100)

GetSystemDirectory(buf,100)

print buf.value

MessageBox = windll.user32.MessageBoxW

MessageBox(None, u"Hello World", u"Hi", 0)

其他

通过ctypes使用回调函数,递归数据类型, 空指针等更多功能,可以参考python文档Generic Operating System Services中的ctypes部分

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值