@真开心啊,聚精会神找一天错误没找到,看个视频摸摸鱼就找到了
首先要明确的怎么导入
项目所需,需要使用pyqt写界面,然后里有涉及电机和摄像头的调用,底层驱动是c语言写好了,并导出了动态库dll文件。
导入方法
可以使用ctypes
和cffi
方法导入,不过好像资料都不多
我用的是ctypes
在python代码的头部导入库
import ctypes
from ctypes import *
AMC = ctypes.cdll.LoadLibrary
lib_amc = AMC("./driver/amc4030/AMC4030.dll") #该文件与python在同一目录下
print("add AMC4030.dll succeed")
一般这样就把动态链接库导入进去了。假设库里有一个函数,名字是
function(int a, int b)
然后开始调用库里的函数
lib_amc.function(1,2)
参数类型怎么匹配
上面这个都是很简单的导入和调用方法,但是我们主要出现的问题是参数类型不匹配。比如报错
TypeError: an integer is required (got type str
比如我dll库里有一个函数原型是
#define temp_SYSTEM 0
···
temp_GetInt( void* ; const wchar_t* , long long* ); //这是原形
temp_GetInt(a, L"count", &temp_count);//调用一般都是这样,里面涉及了长字符串,指针,void*
是不是在python里调用就蒙了。。。
众所周知,L"count"
, 这样count
的类型是长字符串型。也就是wchar_t。后面的&temp_count,也就是一个长整型取地址
ctypes就是做这个类型转换的,这个时候就需要一个c类型和python类型对应成ctypes的表了
也就是你在python代码里用ctypes类型代替c语言里有但是python里没有的类型,比如指针是吧。
ctypes基本C兼容数据类型对应表
ctypes 类型 | c类型 | python 类型 |
---|---|---|
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 |
上面这个表就是对应了python里的怎么改C库数据类型
指针怎么改
指针的改法如下
给他加个byref
最后这么调用的
FX = ctypes.cdll.LoadLibrary
lib_fx = FX("./driver/fx17/SpecSensor.dll")
nDeviceCount = 0
c_nDeviceCount = c_longlong(nDeviceCount)
lib_fx.SI_GetInt(0, c_wchar_p('DeviceCount'), byref(c_nDeviceCount))