Python: module not found (OSError: [WinError 126]) when loading a DLL using FFTW

Python: module not found (OSError: [WinError 126]) when loading a DLL using FFTW

我正在使用 Visual Studio 2015FFTW 创建 dll。然后我使用

在 Python 下加载 dll
libc = cdll.LoadLibrary('D:\Library_C\x64\Release\Library_C.dll')

在 Visual Studio 下,我链接到 FFTW .lib 库,当然(libfftw3-3.liblibfftw3f-3.liblibfftw3l-3.lib)。一切都很好。 dll 也被创建。

但是Python不小心说找不到模块

如果我从编译代码中删除对 FFTW 函数的任何调用,Python 会找到该模块。

我该如何解决这个问题?

如有任何帮助,我将不胜感激。

编辑

我收到的错误代码是

OSError: [WinError 126]

谷歌搜索,我注意到在加载外部 dlls 时,这种错误代码在 Python 中很常见。

很有可能是找不到libfftw3 dll造成的。

对于一个简短的测试,Python 程序和所有 DLL 可以简单地存储在同一目录中。然后启动您的命令提示符并切换到该目录 (!) 并通过键入 python <your.py> 从命令行启动您的 Python 程序。所以所有需要的DLL都在当前目录中,可以找到。

请注意,在使用导入库时(很有可能),您自己的 dll 并未静态链接到 fftw 库。因此必须在运行时找到 libfftw3 dll。有几种方法可以做到这一点。

DLL 搜索顺序

有一篇关于 DLL 搜索顺序的 Microsoft 文档:

https://docs.microsoft.com/en-us/windows/desktop/dlls/dynamic-link-library-search-order

例如有以下几种可能:

  • 当前目录(如果您使用命令行)

  • 将DLL所在目录添加到环境变量PATH

  • 正如@JackOLantem 提到的,您还可以直接从您的 Python 程序

  • 加载隐式依赖库

说明

如果我上面的评论不能解决问题,这里有一个 step-by-step 指南和一个简单的测试用例。我已尝试使测试用例尽可能接近您的示例。

创建导入库

如果您在 64 位机器上工作并安装了 64 位 Python,请不要忘记使用 /machine:x64 参数:

lib /machine:x64 /def:libfftw3-3.def

创建您自己的 dll,它引用一些 libfftw3 函数,例如像这样:

#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);
}

在 Visual Studio 中切换到 x64 配置以构建 64 位 dll。

  • 在配置 Properties/Linker/Input 下 Additional Dependencies 添加 libttfw3-3.lib。

  • 在配置 Properties/Linker/General 下将 .lib 所在的路径添加到 Additional Library Directories

Python 测试

Python 测试程序如下所示:

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())

不需要使用绝对路径。如果你将 Library_C.dll 也放入 .py 文件所在的文件夹中,你可以只写:

libc = ctypes.cdll.LoadLibrary('Library_C.dll')

结果是一样的。如果您喜欢不同的解决方案,当然也适用 Windows dll 的标准搜索顺序。

结果

将 libfftw3-3.dll 复制到 .py 文件所在的同一目录后,您可以通过以下方式调用它:

cd <dir-with-python-program-and-dlls>
python test.py

结果类似于:

b'(dft-ct-dit/8\n  (dftw-direct-8/12 "t3fv_8_avx")\n  (dft-direct-16-x8 "n2fv_16_avx"))'

重要

Stephan Schlecht 的步骤在以下步骤之前是必要的。

解决方案

Dependencies 工具对我很有帮助。它清楚地表明了对 libfftw3-3.dll.

的依赖

引用斯蒂芬的话

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 the libfftw3 dlls must be found at runtime.

然而,仅仅将 FFTW dll 放入同一个 .py 目录是不够的。我需要显式加载它:

FFTWFile    = 'D:\FFTW64\libfftw3-3.dll'
FFTW64      = cdll.LoadLibrary(FFTWFile)