Python Ctypes : Loading C++ DLL - "module not found" or "function ' fn_12 3' not found"

标签 python c++ dll wrapper ctypes

我正在尝试从已编译(不是由我编译)的 C++ DLL 文件中加载和调用函数。

我遇到了两个有问题的场景:

  1. 使用 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
    
  2. 使用 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

过去几天我一直在研究这个问题,非常感谢指出正确方向的观点。

最佳答案

我的具体问题的解决方案是:

  1. 确保正确安装 MATLAB
  2. 确保依赖的 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/

相关文章:

python - 为什么不能使用同一个处理程序多次读取一个文件?

java - 新闻的代码拆分/格式 - 需要权威提及

python - 如何从列表中随机调用任何方法

c++ - boost::log 在容器中保存消息,然后将所有消息发送到后端

c++ - spy++如何找出屏幕上某一点的窗口是什么?

C# 派生接口(interface)在 C++ 中无法正常工作

c# - 为什么 .NET 找不到 OpenSSL.NET dll?

c++ - Windows 7 上的 DLL 重定向

python - while循环在django中递增范围

c# - 如何从 C# 获取和发送 UTF-8 中的字符串到 C++ DLL