@真開心啊,聚精會神找一天錯誤沒找到,看個視訊摸摸魚就找到了
專案所需,需要使用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裡沒有的型別,比如指針是吧。
c 型別 | python 型別 | ctypes 型別 |
---|---|---|
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))