Python: модуль не найден (OSError: [WinError 126]) при загрузке DLL с использованием FFTW - PullRequest
0 голосов
/ 20 мая 2019

Я создаю dll, используя Visual Studio 2015 и FFTW. Затем я загружаю dll под Python, используя

libc = cdll.LoadLibrary('D:\\Library_C\\x64\\Release\\Library_C.dll')

В Visual Studio я, конечно, связываюсь с библиотеками FFTW .lib (libfftw3-3.lib, libfftw3f-3.lib, libfftw3l-3.lib). Все компилируется нормально. dll также создан.

Тем не менее, Python неожиданно говорит, что модуль не может быть найден.

Если я удаляю любой вызов функций FFTW из скомпилированного кода, Python находит модуль.

Как мне решить проблему?

Буду признателен за любую помощь.

EDIT

Код ошибки, который я получил, был

OSError: [WinError 126]

Погуглив, я заметил, что такой код ошибки довольно часто встречается в Python при загрузке внешних dll с.

Ответы [ 2 ]

1 голос
/ 20 мая 2019

Скорее всего, это вызвано тем, что DLL (и) libfftw3 не могут быть найдены.

Для краткого теста программа Python и все библиотеки DLL могут быть просто сохранены в одном каталоге. Затем запустите командную строку и перейдите в этот каталог (!) И запустите программу Python из командной строки, набрав python <your.py>. Таким образом, все необходимые библиотеки DLL находятся в текущем каталоге и могут быть найдены.

Обратите внимание, что ваша собственная dll статически не связана с библиотеками fftw при использовании библиотек импорта (скорее всего). Таким образом, библиотеки libfftw3 должны быть найдены во время выполнения. Есть несколько способов сделать это.

Порядок поиска DLL

Существует документ Microsoft о порядке поиска DLL:

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

Например, есть следующие возможности:

  • текущий каталог (если вы работаете из командной строки)

  • добавление каталога, в котором находятся библиотеки DLL, к переменной среды PATH

  • и, как упоминает @JackOLantem, вы также можете загружать неявные зависимые библиотеки непосредственно из вашей программы на Python

Инструкция

Если мой комментарий выше не решит проблему, вот пошаговое руководство с простым тестовым примером. Я постарался максимально приблизить тестовый пример к вашему примеру.

Создание библиотек импорта

Если вы работаете на 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.

  • в свойствах конфигурации / компоновщик / ввод в Additional Dependencies добавить libttfw3-3.lib.

  • в разделе Configuration Properties / Linker / General добавьте путь, в котором находится .lib, к Additional Library Directories.

Python Test

Тестовая программа 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"))'
0 голосов
/ 21 мая 2019

Важно

Шаги Штефана Шлехта необходимы перед приведенными ниже.

Решение

Инструмент Зависимости мне очень помог. Это ясно указывало на зависимость от libfftw3-3.dll.

Цитата Стефана

Скорее всего, это вызвано тем, что libfftw3 dll (s) не может быть найден.

Для быстрого теста просто поместите его в ту же директорию, где находится .py файлы находятся.

Обратите внимание, что ваш собственный dll статически не связан с fftw библиотеки при использовании библиотек импорта (скорее всего). Так что libfftw3 dll s должны быть найдены во время выполнения.

Однако простого помещения FFTW dll в тот же каталог .py было недостаточно. Мне нужно было загрузить его явно:

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