python 調用dll 動態鏈接庫 結構體參數及回調函數等示例


結構體示例:

這里是 C 代碼的部分,主要是結構體的聲明和回調函數定義。

// 新版本定義
typedef enum {
    DevCard,
    DevLocator,
    DevReader
} DevType;

typedef enum {
    MsgLocate,      // 定位信號
    MsgCut,         // 剪斷信號
    MsgHeartBeat,   // 心跳信號
    MsgCall,        // 呼叫信號
    MsgShake,       // 震動信號
    MsgLeave,       // 離開信號
    MsgOffAlarm,    // 報警燈關閉信號
    MsgCheckPower,  // 電量檢測信號
    MsgHeartRate,   // 心率信號
    MsgExtra,       // 補發信號
    MsgNoPower,     // 沒電信號
    MsgReset,       // 重置信號
    MsgBoundary,    // 跨界信號
    // 此消息會跟隨着MsgLocate消息出現
    MsgPower,
    // 當checkOffline設置為1時有效。如果在offlineTime時間內沒有收到此設備的信號,則發出離線信號
    MsgOffline,
    MsgLast
} MsgType;

// 由於消息類型的不同,不是所有的值都有意義
typedef struct {
    MsgType type;
    DevType device;         // 硬件類型
    int32_t cardID;         // 標簽/腕帶ID,當DevType為DevCard時有意義
    int32_t readerID;       // 閱讀器ID,總是有意義
    int32_t locatorID;      // 大於0時有意義,表示定位器ID
    int32_t readerRSSI;     // 閱讀器信號強度,由於硬件版本的差異,此值要么全有意義,要么全沒意義(總是0)
    int32_t locatorRssiX;   // 當MsgType為[MsgLocate, MsgExtra]時,此值有意義,表示定位器的信號強度
    int32_t locatorRssiY;   // 定位器的信號強度
    uint8_t isCut;          // 如果此值為1,表示硬件被破壞。因為有專門的MsgCut消息,可以忽視此值
    uint8_t isShake;        // 如果此值為1,表示硬件處於震動狀態。僅當MsgType為MsgShake是有意義,1表示震動,0表示靜止
    uint8_t isLowpower;     // 硬件是否低電。硬件為標簽時有意義,因為有追加的MsgPower消息,可以在MsgType為MsgPower時使用此值
    int32_t heartRate;      // 心率,當MsgType為[MsgHeartBeat, MsgHeartRate]之一時有意義
    int32_t power;          // 電量,當MsgType為[MsgHeartBeat, MsgReset, MsgCheckPower]之一時有意義
    int64_t time;           // 消息時間戳
    int     version;        // 硬件版本號,DevType為DevCard時有意義
} DevMsg;

typedef void(*MsgCallback)(DevMsg msg, void *ctx);


extern "C" {
	DEVSDK_API int ccrfidDevSdkStartWork(MsgCallback fun, void *ctx);
}
# coding=UTF-8
from ctypes import *
import time
import _ctypes


# 定義回調函數參數的結構體
class DevMsg(Structure):
    _fields_ = [("type", c_long),
                ("device", c_long),
                ("cardID", c_long),
                ("readerID", c_long),
                ("locatorID", c_long),
                ("readerRSSI", c_long),
                ("locatorRssiX", c_long),
                ("locatorRssiY", c_long),
                ("isCut", c_char),
                ("isShake", c_char),
                ("isLowpower", c_char),
                ("heartRate", c_long),
                ("power", c_long),
                ("time", c_longlong),
                ("version", c_long)]

注意一下 _fields_的內容:這里就是對 C 數據類型的轉換。左邊是 C 的結構成員名稱,右邊則是在 python 中聲明一下各個成員的類型。其他的一些類型請參見官方文檔。

此外還需要注意一下類似於 c_int, c_void_p 等等的定義是在 ctypes 中的,如果是用import ctypes 的方式包含 ctypes 模塊,則應該寫成 ctypes.c_long, ctypes.c_longlong,ctypes.c_char

第三個要注意的是:這個類必須定義為 ctypes.Structure 的子類,否則在進行后續的函數傳遞時,ctypes 由於不知道如何進行數據類型的對應,會拋出異常

回調函數示例:

# 定義功能類與方法
class DemoDll:

    def __init__(self):
        self.dll = cdll.LoadLibrary('ccrfidDevSDK.dll')
        return

    def ccrfidDevSdkStartWork(self, callback, p):
        return self.dll.ccrfidDevSdkStartWork(callback, p)


# ctypes通過 CFUNCTYPE 支持回調函數,定義返回值與參數,第一個參數表示返回值,void為None
CALLBACK = CFUNCTYPE(None, POINTER(DevMsg))   

最后的 CALLBACK通過 ctypes 定義了一個回調函數類型,這個在后面的調用中需要使用
CFUNCTYPE 后面的第一個參數為 None,這表示回調函數的返回值類型為 void

完整功能示例:

# coding=UTF-8
from ctypes import *
import time
import _ctypes


# 定義回調函數參數的結構體
class DevMsg(Structure):
    _fields_ = [("type", c_long),
                ("device", c_long),
                ("cardID", c_long),
                ("readerID", c_long),
                ("locatorID", c_long),
                ("readerRSSI", c_long),
                ("locatorRssiX", c_long),
                ("locatorRssiY", c_long),
                ("isCut", c_char),
                ("isShake", c_char),
                ("isLowpower", c_char),
                ("heartRate", c_long),
                ("power", c_long),
                ("time", c_longlong),
                ("version", c_long)]


# 定義功能類與方法
class DemoDll:

    def __init__(self):
        self.dll = cdll.LoadLibrary('ccrfidDevSDK.dll')
        return

    def ccrfidDevSdkStartWork(self, callback, p):
        return self.dll.ccrfidDevSdkStartWork(callback, p)


# ctypes通過 CFUNCTYPE 支持回調函數,定義返回值與參數,第一個參數表示返回值,void為None,第二參數為回調函數的參數為結構體指針
CALLBACK = CFUNCTYPE(None, POINTER(DevMsg))


# 回調函數距離功能實現 
def _callback(para):
    # print(dir(para))
    obj = para.__getitem__(0)
    print(obj.type, obj.cardID, obj.readerID, obj.locatorID, obj.heartRate, obj.power, obj.time, obj.version)


# 定義回調函數
callBackFunc = CALLBACK(_callback)

# 實例化功能類
dll = DemoDll()
# 定義一個空的指針
null_ptr = POINTER(c_int)()
# 具體功能調用
c = dll.ccrfidDevSdkStartWork(callBackFunc, null_ptr)

print(c)

time.sleep(100000)

運行結果
在這里插入圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM