Python之ctypes模块用法

目录

 

简要说明

开发环境

封装数据结构

数组

结构体

指针

枚举 

函数传递结构体参数 

 备注


简要说明

  ctypes是Python的外部函数库。它提供C兼容的数据类型,并允许在DLL或共享库中调用函数,它可以用于在纯Python中包装这些库。cdll 加载使用标准cdecl调用约定导出函数的库,而windll库使用stdcall 调用约定调用函数。调用形式如下:

from ctypes import *

clib = windll.LoadLibrary("C:\\Users\\ad\\Desktop\\python_test\\Python_visa_test\\XXX.dll")

开发环境

操作系统:window7

python版本:3.4.4

编辑器:vscode,作为一款跨平台轻量级的编辑器,完全可以替代vs,推荐大家使用

封装数据结构

对于C语言中经常用到的数组、结构体、指针、枚举等类型,ctypes模块都提供了封装。ctypes定义了许多原始的C兼容数据类型,如下:

数组

#char型的一位数组,长度为8

x = c_char * 8

#int型的一位数组,长度为8

y= c_int * 8

#int型的二维数组(等同于c语言: int z[8][256])

z = y*256

结构体

ctypes中将结构体封装成类,需要继承Structure,在_fields_中定义成员,如下:

class DeviceInfo(Structure):

       x= c_char * 8

       y = c_char * 8

       z= c_char * 8

       _fields_ = [("x1",x* 256),   #二维数组

                        ("y1",y* 256),

                        ("z1",z* 256),

                        ("n",c_int * 8),

                        ("m",c_int),

                        ("a",c_int),

                        ("b",c_char * 8 )]

指针

通过pointerctypes类型上调用函数 来创建指针实例:

from ctypes import *
i = c_int(42)
pi = pointer(i)

指针实例有一个contents属性,它返回指针指向的i对象,上面的对象:

>>> pi.contents
c_long(42)
>>>

注意,ctypes没有OOR(原始对象返回),每次检索属性时它都会构造一个新的等效对象 :

>>> pi.contents is i
False
>>> pi.contents is pi.contents
False
>>>

将另一个c_int实例分配给指针的contents属性会导致指针指向存储它的内存位置:

>>> i = c_int(99)
>>> pi.contents = i
>>> pi.contents
c_long(99)
>>>

pointer()函数不仅仅是创建指针实例,还必须首先创建指针类型。这是通过POINTER()接受任何ctypes类型的函数完成的 ,并返回一个新类型 :

>>> PI = POINTER(c_int)
>>> PI
<class 'ctypes.LP_c_long'>
>>> PI(42)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected c_long instead of int
>>> PI(c_int(42))
<ctypes.LP_c_long object at 0x...>
>>>

调用不带参数的指针类型会创建一个NULL指针。 NULL指针有一个False布尔值:

>>> null_ptr = POINTER(c_int)()
>>> print(bool(null_ptr))
False
>>>

ctypes检查NULL何时解除引用指针(但解除引用无效的非NULL指针会使Python崩溃): 

>>> null_ptr[0]
Traceback (most recent call last):
    ....
ValueError: NULL pointer access
>>>

>>> null_ptr[0] = 1234
Traceback (most recent call last):
    ....
ValueError: NULL pointer access
>>>

枚举 

枚举需要继承Enum,如下:

from enum import Enum

class Cand(Enum):

       x= 0

        y= 1

函数传递结构体参数 

C库中有这样一个函数:

int getDevInfo(DeviceInfo *info,int counter,char *callBack);

在ctypes中传递结构体,只能传递结构体指针,不能传递实例对象,并且调用C库中的函数参数必须以ctypes基本数据类型封装才能调用,如下:

 

#调用C库函数

getDevInfo = clib .getDevInfo

#告诉ctypes数据类型

getDevInfo .argtypes= [POINTER(DeviceInfo ),c_int,POINTER(c_char)]

t_callBack = c_char()

#创建一个结构体实例

t_devInfo = AllDeviceInfo()

ret = getDevInfo (byref(t_devInfo ),c_int(3),byref(t_callBack))

if(ret < 0):

      print("CALL FAILED!")

else:

      print("CALL SUCCESS!")

 备注

在这里只介绍了一些ctypes模块常用的地方,感兴趣的同学,可以参照官方教程:https://docs.python.org/3.5/library/ctypes.html#

展开阅读全文

没有更多推荐了,返回首页