• 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)
    

    运行结果
    在这里插入图片描述

  • 相关阅读:
    HDFS 常用命令
    CentOS6.5和RedHat6.5下以rpm方式安装mysql-5.6.20
    RedHat安装yum+配置国内yum源
    nginx 一般配置实例 静态页面
    PHP计划任务之关闭浏览器后仍然继续执行的函数 ignore_user_abort
    php函数——『解析 xml数据』
    基于php-fpm的配置详解[转载]
    解决nginx: [error] open() "/usr/local/nginx/logs/nginx.pid" failed错误
    nginx的优化
    Nginx fastcgi_param解释
  • 原文地址:https://www.cnblogs.com/gmhappy/p/11863950.html
Copyright © 2020-2023  润新知