I'm trying to load AND call functions from an already compiled (not by me) C++ DLL file.
I'm faced with two problematic scenarios:
Loading DLL by using CDLL():
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
which gives me the module not found 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
Loading the same DLL by using win32api.LoadLibraryEx() then CDLL()
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
which is able to load the DLL.
However, when attempting to call functions within this DLL, the following AttributeError is raised:
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
After extensive online research and consulting the Ctypes documentation, I have tried the following historical solutions:
- Use Dependency Walker to check dependencies
- Ensure all DLL dependencies are placed in the same directory
- Add the DLL directory to system PATH
- Ensure
extern "C"
is added to the C++ header file to prevent name mangling - Using keyword
EXPORTED_FUNCTION
in the C++ header file - Setting the current working directory in Python to that of the DLL file directory prior to loading DLLs
without any success...
I've also compiled my own SEPARATE 64-bit C++ DLL file (completely independent from the aa_Functions.dll file previously mentioned) in Microsoft Visual Studio 2010 in both Debug and Release modes, with test functions included inside.
This test DLL is able to be loaded, and its functions called successfully, per the following:
__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
With the expected console output:
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
I've spent the last several days on this issue and a point in the right direction would be tremendously appreciated.