我正在尝试从已编译(不是由我编译)的 C++ DLL 文件中加载和调用函数。
我遇到了两个有问题的场景:
使用 CDLL() 加载 DLL:
from ctypes import * __path_aa_Fn_dll__ = r'C:\user\aacad_2017\aa_Functions.dll' # DLL file path aa_Fn_dll = CDLL(__path_aa_Fn_dll__) # load DLL
这给了我找不到模块的 OSError:
Traceback (most recent call last): File "C:/user/aacad_2017/cadClass.py", line 189, in <module> aa_Fn_dll = CDLL(__path_aa_Fn_dll__) File "C:\Users\user\AppData\Local\Continuum\anaconda3\lib\ctypes\__init__.py", line 348, in __init__ self._handle = _dlopen(self._name, mode) OSError: [WinError 126] The specified module could not be found
使用 win32api.LoadLibraryEx() 然后 CDLL() 加载相同的 DLL
aa_Fn_dll_handle = win32api.LoadLibraryEx(__path_aa_Fn_dll__, 0, win32con.LOAD_LIBRARY_AS_DATAFILE) # get DLL handle aa_Fn_dll = CDLL(__path_aa_Fn_dll__, handle=aa_Fn_dll_handle) # load DLL
能够加载DLL。
但是,当尝试调用此 DLL 中的函数时,会引发以下 AttributeError:
aa_Fn_dll.aaBIN2iv.restype = c_double # set function return type aa_Fn_dll.aaBIN2iv.argtypes = [c_double, c_double, c_double, c_double, c_double, c_double, c_double, c_char_p] # set function argument types aa_Fn_dll.aaBIN2iv(10, 10, 10, 10, 10, 10, 10, b"C") # call DLL function Traceback (most recent call last): File "C:/user/aacadMatlabWrap_2017_new_test/cadClass.py", line 196, in <module> aa_Fn_dll.aaBIN2iv.restype = c_double File "C:\Users\user\AppData\Local\Continuum\anaconda3\lib\ctypes\__init__.py", line 361, in __getattr__ func = self.__getitem__(name) File "C:\Users\user\AppData\Local\Continuum\anaconda3\lib\ctypes\__init__.py", line 366, in __getitem__ func = self._FuncPtr((name_or_ordinal, self)) AttributeError: function 'aaBIN2iv' not found
经过广泛的在线研究和查阅 Ctypes 文档,我尝试了以下历史解决方案:
- 使用 Dependency Walker 检查依赖项
- 确保所有 DLL 依赖项都放在同一目录中
- 将DLL目录加入系统PATH
- 确保将
extern "C"
添加到 C++ 头文件以防止名称混淆 - 在 C++ 头文件中使用关键字
EXPORTED_FUNCTION
- 在加载 DLL 之前将 Python 中的当前工作目录设置为 DLL 文件目录的目录
没有任何成功......
我还在 Microsoft Visual Studio 2010 中以调试和 Release模式编译了我自己的独立 64 位 C++ DLL 文件(完全独立于前面提到的 aa_Functions.dll 文件),其中包含测试函数。
这个测试DLL能够被加载,并且它的函数调用成功,如下所示:
__path_test_dll__ = r'C:\user\dllTest\x64\Release\dllTest.dll' # test DLL file path
test_dll = CDLL(__path_test_dll__) # load test DLL
test_dll.fn4.restype = c_void_p # set test DLL function return type
test_dll.fn4.argtypes = [c_double, c_double, c_double, c_char_p, c_bool] # set test DLL function argument types
test_dll.fn4(10, 12, 1, b"Pay", True) # make test DLL function call
具有预期的控制台输出:
Min_P * Rate == $10
Pay: 1 Min_P: 10 Max_P: 12 Iteration #: 1
Min_P * Rate == $11
Pay: 0 Min_P: 11 Max_P: 12 Iteration #: 2
Min_P * Rate == $12
Pay: 1 Min_P: 12 Max_P: 12 Iteration #: 3
Process finished with exit code 0
过去几天我一直在研究这个问题,非常感谢指出正确方向的观点。
最佳答案
我的具体问题的解决方案是:
- 确保正确安装 MATLAB
- 确保依赖的 MATLAB DLL (libmx.dll) 目录已添加到 PATH 并且可以在加载实际 DLL 之前使用
ctypes
加载
事后看来,这是一个非常简单的问题 - 缺少 DLL 依赖项。但是找到特定丢失的 DLL 可能是一个挑战。
关于Python Ctypes : Loading C++ DLL - "module not found" or "function ' fn_12 3' not found",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50497472/