使用ctypes调用第三方DLL函数时提示函数未找到但实际存在
Python调用第三方DLL函数失败的解决方法
问题根源
从你提供的Dependencies工具输出可以看到,函数sdk_get_data确实存在,但ctypes按原名称查找失败,大概率是函数名被C++编译修饰(Name Mangling),或者DLL仅通过序号导出函数(输出里的1 (0x0001)就是该函数的导出序号)。
可行解决方案
方案1:通过函数序号直接调用
利用Dependencies给出的导出序号(1)获取函数,这是最直接的方式:
import ctypes sdk = ctypes.cdll.LoadLibrary("./Library.dll") # 通过序号1获取目标函数 get_data = sdk[1] # 必须指定函数的参数类型和返回类型,否则调用会引发内存错误 get_data.argtypes = [ctypes.c_char_p, ctypes.c_int, ctypes.POINTER(ctypes.c_ushort), ctypes.POINTER(ctypes.c_ubyte)] get_data.restype = ctypes.c_int
方案2:使用C++修饰后的函数名调用
如果序号调用无效,可在Dependencies中查看该函数的修饰后全名(比如类似_sdk_get_data@16的格式),然后用修饰名查找:
import ctypes sdk = ctypes.cdll.LoadLibrary("./Library.dll") # 替换为实际的修饰后函数名 get_data = sdk._sdk_get_data@16 # 同样必须指定参数和返回类型 get_data.argtypes = [ctypes.c_char_p, ctypes.c_int, ctypes.POINTER(ctypes.c_ushort), ctypes.POINTER(ctypes.c_ubyte)] get_data.restype = ctypes.c_int
是否需要编写C++ Wrapper?
不需要。只要能通过序号或正确的修饰名获取到函数地址,并且正确指定参数和返回类型,就可以直接用ctypes调用。只有当DLL涉及复杂的C类、模板或自定义复杂结构体时,才需要考虑编写C wrapper做中转。
额外注意事项
- 再次确认Python与DLL的架构完全匹配:32位DLL必须搭配32位Python,64位DLL搭配64位Python,避免架构混用。
- 调用函数时参数类型必须严格匹配:比如
char*对应Python的bytes类型,不能直接传字符串;指针类型需要用ctypes的对应类型创建变量后取地址(例如ctypes.c_ushort()创建变量后用ctypes.byref()传入)。
内容的提问来源于stack exchange,提问作者Megan Caithlyn
相关产品推荐
相关产品推荐

