Reputation: 21475
I'm creating a dll
using Visual Studio 2015
and FFTW
. I'm then loading the dll
under Python using
libc = cdll.LoadLibrary('D:\\Library_C\\x64\\Release\\Library_C.dll')
Under Visual Studio, I'm linking against the FFTW .lib
libraries, of course (libfftw3-3.lib
, libfftw3f-3.lib
, libfftw3l-3.lib
). Everything compiles fine. The dll
is also created.
However, Python unespectedly says that the module cannot be found.
If I remove any invocation to FFTW
functions from within the compiled code, Python finds the module.
How can I solve the problem?
I would be grateful for any help.
EDIT
The error code I received was
OSError: [WinError 126]
Googling around, I have noticed that such an error code is quite common in Python
when loading external dll
s.
Upvotes: 0
Views: 503
Reputation: 27106
Most likely it is caused due to the fact that the libfftw3 dll(s) can't be found.
For a short test, the Python program and all DLLs can simply be stored in the same directory. Then start your command prompt and change to this directory(!) and start your Python program from the command line by typing python <your.py>
. So all required DLLs are in the current directory and can be found.
Please note that your own dll is not statically linked to the fftw libraries when using import libraries (most likely). So the libfftw3 dlls must be found at runtime. There are several ways to do this.
DLL Search Order
There is a Microsoft document about the DLL search order:
https://learn.microsoft.com/en-us/windows/desktop/dlls/dynamic-link-library-search-order
For example, there are the following possibilities:
the current directory (if you are working from the command line)
adding the directory in which the DLLs are located to the environment variable PATH
and as @JackOLantem mentions, you can also load implicit dependent libraries directly from your Python program
Instructions
If my comment above doesn't solve the problem, here is a step-by-step guide with a simple test case. I have tried to keep the test case as close as possible to your example.
Create Import Libraries
If you are working on a 64-bit machine with a 64-bit Python installation, don't forget to use the /machine:x64 argument:
lib /machine:x64 /def:libfftw3-3.def
Create your own dll which references some libfftw3 functions, e.g. like so:
#include "windows.h"
#include "fftw3.h"
#define NUM_POINTS 128
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
__declspec(dllexport) char *plan() {
fftw_complex signal[NUM_POINTS];
fftw_complex result[NUM_POINTS];
fftw_plan plan = fftw_plan_dft_1d(NUM_POINTS,
signal,
result,
FFTW_FORWARD,
FFTW_ESTIMATE);
return fftw_sprint_plan(plan);
}
In Visual Studio switch to x64 configuration to build a 64-bit dll.
under Configuration Properties/Linker/Input under Additional Dependencies
add libttfw3-3.lib.
under Configuration Properties/Linker/General add the path where the .lib resides to Additional Library Directories
.
Python Test
The Python test program would look like this:
import ctypes
libc = ctypes.cdll.LoadLibrary('C:\\Users\\stephan\\Documents\\pyfftw\\Library_C\\x64\\Debug\\Library_C.dll')
libc.plan.restype = ctypes.c_char_p
print(libc.plan())
One doesn't need to use an absolute path. If you put the Library_C.dll also into the folder where the .py file is located you can just write:
libc = ctypes.cdll.LoadLibrary('Library_C.dll')
The result is the same. Also of course the standard search order for Windows dlls apply if you prefer a different solution.
Result
After you copy the libfftw3-3.dll into the same directory where the .py file resides you can call it by:
cd <dir-with-python-program-and-dlls>
python test.py
The result is something like:
b'(dft-ct-dit/8\n (dftw-direct-8/12 "t3fv_8_avx")\n (dft-direct-16-x8 "n2fv_16_avx"))'
Upvotes: 1
Reputation: 21475
Important
The steps by Stephan Schlecht are necessary before the below ones.
Solution
The Dependencies tool was quite helpful for me. It clearly indicated the dependency on libfftw3-3.dll
.
Quoting Stephan
Most likely it is caused due to the fact that the
libfftw3
dll
(s) can't be found.For a quick test just put it in the same directory where your
.py
files resides.Please note that your own dll is not statically linked to the
fftw
libraries when using import libraries (most likely). So thelibfftw3
dll
s must be found at runtime.
However, simply putting the FFTW
dll
into the same .py
directory was not sufficient. I needed to load it explicitly:
FFTWFile = 'D:\\FFTW64\\libfftw3-3.dll'
FFTW64 = cdll.LoadLibrary(FFTWFile)
Upvotes: 0