我想为
win_amd64
(Windows x64) 的 cpp 文件制作一个 Python 包。我使用 Swig 将它们包装到 python 中,然后使用 setuptools 来构建它。我制作了 CMakeLists.txt 文件来执行所有这些操作。 注意:我正在使用 x86_64-w64-mingw32 交叉编译器在 Linux 机器中构建它
使用的工具及版本:
注意:我可以为 linux-x86_64 (linux 64) 为所有 Python3.6 及更高版本构建 python pkg,但对于 Windows,我只能为 Python3.6 构建(通过使用库 libpython36.a),但使用win_amd64 的更高版本我必须使用 libpython39.lib (基于 Lib 的库)
现在发生了什么:
我可以成功构建win_amd64的whl文件。 CMake可以让.dll和setuptools很好的包裹它
在 Windows Python3.9 x64 上安装此程序时,它会在没有任何警告的情况下安装
但是当我尝试导入主模块时,它抛出了
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.`
项目设置:
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)
swig使用的接口文件:
%module arithmetic_operator
%{
#include "addition.h"
%}
%include "addition.h"
%include "stdint.i"`
头文件:
# include <iostream>
using namespace std;
int addition_fn(int a, int b)
{
return (a+b);`
}
CPP 文件:
# include <iostream>
using namespace std;
const int MAX_ADDABLE = 50;
int main()
{
cout<<"Hello World\n";
}
设置.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 覆盖 - 不起作用
一个月都没搞清楚。
我最终通过将 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 的句柄