导入错误:DLL 加载失败:无法使用 Swig 和 CMake 为自定义构建的 pkg 找到指定的模块

问题描述 投票:0回答:1

我想为

win_amd64
(Windows x64) 的 cpp 文件制作一个 Python 包。我使用 Swig 将它们包装到 python 中,然后使用 setuptools 来构建它。我制作了 CMakeLists.txt 文件来执行所有这些操作。 注意:我正在使用 x86_64-w64-mingw32 交叉编译器在 Linux 机器中构建它

使用的工具及版本:

  • Swig 版本:4.1.1
  • CMake 版本:3.27
  • Python 版本:3.9.18 (linux) - 运行 setuptools
  • 交叉编译工具链:x86_64-w64-mingw32
  • Linux 发行版和版本:Ubuntu 20.04
  • Python 3.9 Windows AMD64 - dev.msi pkg(wget'ed dev.msi 并将其解压到本地文件夹)

注意:我可以为 linux-x86_64 (linux 64) 为所有 Python3.6 及更高版本构建 python pkg,但对于 Windows,我只能为 Python3.6 构建(通过使用库 libpython36.a),但使用win_amd64 的更高版本我必须使用 libpython39.lib (基于 Lib 的库)

现在发生了什么:

  1. 我可以成功构建win_amd64的whl文件。 CMake可以让.dll和setuptools很好的包裹它

  2. 在 Windows Python3.9 x64 上安装此程序时,它会在没有任何警告的情况下安装

  3. 但是当我尝试导入主模块时,它抛出了

    import sample # name of the module
    # Error below
    Traceback:
    from . import _sample_swig
    ImportError: DLL load failed: The specified module could not be found.ImportError: DLL load failed: The specified module could not be found.`
    

项目设置:

  1. Swig 文件

    FIND_PACKAGE(SWIG REQUIRED)
    INCLUDE(${SWIG_USE_FILE})
    CMAKE_MINIMUM_REQUIRED(VERSION 3.16)
    SET(PYTHON_MODULE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sample)
    set(PYTHON_EXECUTABLE python${PYTHON_BUILD_VERSION})
    if (${BUILD_PLATFORM} MATCHES "Windows")
        set(CMAKE_SYSTEM_NAME Windows)
        set(CMAKE_C_COMPILER   /usr/bin/x86_64-w64-mingw32-gcc)
        set(CMAKE_CXX_COMPILER /usr/bin/x86_64-w64-mingw32-g++)
        set(PYTHON_LIBRARY /home/developer/workspace/69/py39/libs/python.lib)
        set(PYTHON_INCLUDE_DIR /home/developer/workspace/69/py39/include)
        set(TARGET_EXTENSION "pyd")
        set(CMAKE_FIND_ROOT_PATH /opt/win_cross_compile_libs)
    
    ELSE()
        set(CMAKE_C_COMPILER /usr/bin/gcc)
        set(CMAKE_CXX_COMPILER /usr/bin/g++)
        set(TARGET_EXTENSION "so")
        set(PythonLibs_DIR /usr/lib/x86_64-linux-gnu/)
        set(CMAKE_FIND_ROOT_PATH /usr/lib/x86_64-linux-gnu/)
    ENDIF()
    project(sample LANGUAGES CXX)
    set(CMAKE_LANGUAGE_COMPILER ${CMAKE_CXX_COMPILER})
    FIND_PACKAGE(Python3 COMPONENTS Interpreter Development)
    FIND_PACKAGE(PythonLibs)
    INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/include)
    message(STATUS "Py Libs: ${PYTHON_LIBRARIES}")
    message(STATUS "Add. Linking Flags: ${ADD_LINK_FLAGS}")
    message(STATUS "Python Incl Dir: ${PYTHON_INCLUDE_DIR}")
    message(STATUS "Python Module: ${PYTHON_MODULE_DIR}")
    message(STATUS "Machine: ${CMAKE_SYSTEM_NAME}")
    set(PythonLibs_DIR "/usr/lib/x86_64-linux-gnu/")
    set_property(SOURCE include/sample.i PROPERTY CPLUSPLUS ON)
    file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/src/*.cpp)
    swig_add_library(sample_swig TYPE SHARED
              LANGUAGE python
              OUTPUT_DIR ${PYTHON_MODULE_DIR}
              OUTFILE_DIR src
              SOURCES include/sample.i ${SRC_FILES}
              )
    SWIG_LINK_LIBRARIES(sample_swig ${PYTHON_LIBRARIES})
    add_custom_command(
    TARGET _sample_swig POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy
         _sample_swig.${TARGET_EXTENSION}
         ${PYTHON_MODULE_DIR}/_sample_swig.${TARGET_EXTENSION}
    )
    
    INSTALL(TARGETS _sample_swig LIBRARY DESTINATION sample)
    
  2. swig使用的接口文件:

    %module arithmetic_operator
    %{
        #include "addition.h"
    %}
    %include "addition.h"
    %include "stdint.i"`
    
  3. 头文件:

    # include <iostream>
    using namespace std;
    
    int addition_fn(int a, int b)
    {
        return (a+b);`
    }
    
  4. CPP 文件:

    # include <iostream>
    using namespace std;
    const int MAX_ADDABLE = 50;
    int main()
    {
        cout<<"Hello World\n";
    }
    
  5. 设置.py:

    from skbuild import setup
    
    setup(
    name='sample',
    version='0.1.0',
    description='Sample',
    cmake_with_sdist=True,
    packages=['sample'],
    python_requires=">=3.6",
    include_package_data=True,
    zip_safe=False
    )
    

使用

os.add_dll_directory(<dll folder location (site-packages/sample)>)
作为 Python3.8 及以上版本仅从可信来源加载,即使被 PYTHONPATH 覆盖 - 不起作用

python cmake cross-compiling swig dllimport
1个回答
0
投票

一个月都没搞清楚。

我最终通过将 Ubuntu 20.04 上 9.0.x 上的 x86_64-w64-mingw32-g++ 移动到 Ubuntu-22.04 上使用 GCC 版本 10-posix 20220113 (GCC) 的编译器 x86_64-w64-mingw32-g++-posix 来解决这个问题

使用共享库时,最新的 GCC 似乎可以处理基于 Windows Python 3.8+ DLL 的句柄

© www.soinside.com 2019 - 2024. All rights reserved.