Python ctypes调用C++ DLL出现LP_LP_c_long类型不匹配报错如何解决
问题根因
存在两个核心错误:
- 代码中
cP = ctypes.POINTER(ctypes.POINTER(ctypes.c_int64))是声明指针类型,而非创建该类型的实例,传参时不能直接传入类型本身。 PMDllWrapperClass::GetDeviceList是C++类非静态成员函数,默认隐含第一个this指针参数,直接按普通C函数调用会出现参数不匹配问题。要么要求DLL提供方导出C风格的扁平接口,要么按对应调用约定手动传入this指针。
解决步骤
假设你已处理成员函数导出问题(比如接口改为静态成员函数或C风格全局导出函数),可按以下步骤调整代码:
1. 定义匹配的结构体
不要直接用c_int64代替自定义结构体,需按照DLL头文件中的定义,声明对应的结构体类型:
import ctypes # 先声明空结构体,后续补全成员 class DEVICE(ctypes.Structure): pass class LAN_DEVICE(ctypes.Structure): pass # 按头文件定义补全结构体成员,示例如下 # DEVICE._fields_ = [ # ("device_id", ctypes.c_int32), # ("device_name", ctypes.c_char * 128), # # 其他成员依次对应声明 # ] # LAN_DEVICE._fields_ 按同样规则补全
2. 声明函数原型、创建参数实例
显式声明函数参数和返回值类型,避免ctypes自动类型推导出错:
# 声明指针类型 PDEVICE = ctypes.POINTER(DEVICE) PLAN_DEVICE = ctypes.POINTER(LAN_DEVICE) # 定义函数参数、返回值类型 PMDll.GetDeviceList.argtypes = [ ctypes.POINTER(PDEVICE), # 对应 DEVICE** pDeviceArray ctypes.POINTER(ctypes.c_int32), # 对应 int* nDeviceCount ctypes.POINTER(PLAN_DEVICE), # 对应 LAN_DEVICE** pLanDeviceArray ctypes.c_int32, # 对应 int LanDeviceCount ctypes.c_int32 # 对应 int InterfaceTypeToSearch ] PMDll.GetDeviceList.restype = ctypes.c_bool # 创建参数实例 p_device_array = PDEVICE() n_device_count = ctypes.c_int32(0) p_lan_device_array = PLAN_DEVICE() # 按实际需求传入搜索参数 lan_device_count = ctypes.c_int32(0) interface_type = ctypes.c_int32(0)
3. 调用函数
二级指针参数需传入一级指针实例的引用:
resultgetdev = PMDll.GetDeviceList( ctypes.byref(p_device_array), ctypes.byref(n_device_count), ctypes.byref(p_lan_device_array), lan_device_count, interface_type )
注意事项
- 如果
GetDeviceList是类非静态成员函数,需要先创建类实例获取this指针,作为第一个参数传入函数,同时调用约定需对应设置为ctypes.WINFUNCTYPE(32位/64位thiscall规则有差异),更推荐使用C风格导出接口,避免处理this指针的额外复杂度。 - 调用成功后可通过
p_device_array[i]访问第i个设备实例,若DLL内部通过动态分配返回内存,需调用DLL提供的对应释放接口释放内存,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Kanat0x
相关产品推荐
相关产品推荐

