使用 Python 加载 C++ 封装好的动态链接库类模板
使用 Python 加载 C++ 封装好的动态链接库类模板需要额外注意的是!!将此模板作为完全的需求侧,那么可以在签名及数据结构定义的时候要求 DLL 的功能,也就是说 DLL 必须实现 此模板 预设的需求,从而实现了开发层面的解耦,所达成的目的就是 DLL 的提供方看到 此模板+业务改动之后 之后就能够秒懂需求0. 定义 C++ 中需要用的数据结构在与 C++ 动态库交互时,首先需要定义与 C++ 结构体对应的 Python 类。通常使用ctypes.Structure来描述这些结构体,确保内存布局一致。fromctypesimportStructure,c_float,c_ubyte,c_int,POINTER,c_void_pimportctypesclassRAW_DATA(Structure):_fields_=[("x",c_float),("y",c_float),("z",c_float)]classDATA_LAYER_1(Structure):_fields_=[("x",ctypes.c_ubyte),("y",ctypes.c_ubyte),("z",ctypes.c_ubyte)]classDATA_LAYER_2(Structure):_fields_=[("ori_data",DATA_LAYER_1*60),("comp_data",RAW_DATA*60),("rest_data",RAW_DATA)]classDATA_NEED(Structure):_fields_=[("data_group",DATA_LAYER_2*10),("num",c_int)]1. 模板类的组成部分该类封装了 DLL 的加载、句柄管理、数据获取以及性能测试等通用功能。主要包含以下部分:单例模式_instance和__new__初始化:链接 DLL、设置函数签名、创建句柄、初始化句柄签名方法(_setup_prototypes)初始化句柄方法(_init_handle)__enter__/__exit__上下文管理器__del__析构方法release显式释放资源benchmark压测方法_analyze_timings计时分析压测结果打印方法print_benchmark_result静态方法is_port_available(判断串口可用性)业务相关方法get_data、get_force2. 创建单例(可选)如果希望全局只有一个实例,可以通过__new__实现单例模式。本例未强制使用,但可以按需添加:classSensorHandler:_instance=Nonedef__new__(cls,*args,**kwargs):ifcls._instanceisNone:cls._instance=super().__new__(cls)returncls._instance3. 初始化初始化过程中完成 DLL 加载、函数签名、句柄创建等操作。def__init__(self):self._lib=ctypes.CDLL(dll_path)# 加载 DLLself._setup_prototypes()# 设置函数签名self._handle=c_void_p()# 句柄变量self._init_handle()# 创建并初始化句柄self._data_buffer=DATA_NEED()# 复用缓冲区,减少分配4. 签名方法签名方法用于告诉ctypes函数参数和返回值类型,避免类型错误。def_setup_prototypes(self):# create_sensor_handle 签名:int create_sensor_handle(void** handle, int mode)self._lib.create_sensor_handle.argtypes=[POINTER(c_void_p),ctypes.c_int]self._lib.create_sensor_handle.restype=c_int# destroy_sensor_handle 签名:int destroy_sensor_handle(void* handle)self._lib.destroy_sensor_handle.argtypes=[c_void_p]self._lib.destroy_sensor_handle.restype=c_int# get_sensor_data 签名:int get_sensor_data(void* handle, DATA_NEED* out)self._lib.get_sensor_data.argtypes=[c_void_p,POINTER(DATA_NEED)]self._lib.get_sensor_data.restype=c_int5. 创建句柄调用 DLL 中的创建函数,得到底层资源句柄。def_init_handle(self):ret=self._lib.create_sensor_handle(ctypes.byref(self._handle),5)ifret!=0:raiseRuntimeError(f"Failed to create handle, error code:{ret}")6.__enter__方法支持上下文管理器,进入时返回自身。def__enter__(self):returnself7.__exit__方法退出上下文时自动释放资源。def__exit__(self,exc_type,exc_val,exc_tb):self.release()8.__del__方法析构函数,确保对象销毁时释放 DLL 资源。def__del__(self):self.release()9.release方法显式释放句柄,避免资源泄漏。defrelease(self):ifself._handle:ret=self._lib.destroy_sensor_handle(self._handle)ifret!=0:print(f"Warning: Failed to destroy handle, error code:{ret}")self._handle=None10.benchmark方法用于性能测试,可测量单次get_data调用耗时或原始 C 函数调用耗时。defbenchmark(self,iterations=1000,warmup=3,include_data_conversion=False):# 预热for_in