pybind11安装很简单,只需要
shellpip install pybind11
编写一个简单的加法函数myadd.cpp
cpp#include <pybind11/pybind11.h>
// 一个简单的 C++ 函数
int add(int i, int j)
{
return i + j;
}
// PYBIND11_MODULE 宏用于定义 Python 模块
PYBIND11_MODULE(myadd, m) // 这里将模块名称改为 'myadd'
{
m.def("add", &add, "A function that adds two numbers");
}
编辑器会在第一行报错,因为它找不到这个文件。此时就要在编辑器的Include Path
中加上
C:\Users\gbwat\AppData\Local\Programs\Python\Python311\Include C:\Users\gbwat\AppData\Local\Programs\Python\Python311\Lib\site-packages\pybind11\include C:\Users\gbwat\AppData\Local\Programs\Python\Python311\libs
这样就不会报错了。此处需要根据自己的python版本和安装位置进行修改
使用CMake编译是非常方便的,我使用的CMakelists.txt
如下
cmakecmake_minimum_required(VERSION 3.12) project(myadd) # 设置 pybind11 的目录路径 set(pybind11_DIR "C:/Users/gbwat/AppData/Local/Programs/Python/Python311/Lib/site-packages/pybind11/share/cmake/pybind11") # 寻找 pybind11 包 find_package(pybind11 REQUIRED) # 设置静态链接 set(BUILD_SHARED_LIBS OFF) # 添加 C++ 模块 pybind11_add_module(myadd myadd.cpp) # 模块名称 'myadd' # 设置输出目录 set_target_properties(myadd PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) # 针对 Windows 平台的额外设置 if (WIN32) target_compile_definitions(myadd PRIVATE NOMINMAX) target_link_libraries(myadd PRIVATE ${PYTHON_LIBRARIES}) # 针对 MinGW 添加静态链接选项 if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") target_link_options(myadd PRIVATE -static-libgcc -static-libstdc++) endif() endif() if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") target_compile_options(myadd PRIVATE -Wall -Wextra -Wpedantic) elseif (MSVC) target_compile_options(myadd PRIVATE /W4 /permissive-) endif() message(STATUS "Using C++ compiler: ${CMAKE_CXX_COMPILER}") message(STATUS "Using Python include directories: ${PYTHON_INCLUDE_DIRS}") message(STATUS "Output library will be placed in: ${CMAKE_CURRENT_SOURCE_DIR}")
注意一定要设置静态链接,否则在python中调用会找不到dll从而出错!!!
在vscode中安装CMAKE
扩展后直接点击生成即可
生成完毕即可在当前目录下找到编译出的文件myadd.cp311-win_amd64.pyd
我使用的是MinGW
编译器,不同的编译器需要使用不同的命令
在当前目录建立一个新文件夹build,在终端中进入文件夹
ahellcd build
随后执行cmake
命令进行配置
shellcmake -G "MinGW Makefiles" ..
随后执行编译
mingw32-make
就可以在上级目录(build文件夹的上级目录)看见编译出的myadd.cp311-win_amd64.pyd
确保python脚本与myadd.cp311-win_amd64.pyd
处于同一目录中,随后直接import
就可以了。一个实例如下
pythonimport myadd
print(myadd.add(1, 2))
运行之,会输出结果3
该情况下CMake会输出
[main] 正在生成文件夹: d:/py/build [build] 正在启动生成 [proc] 执行命令: "C:\Program Files\CMake\bin\cmake.EXE" --build d:/py/build --config Debug --target all -j 24 -- [build] [ 50%] Linking CXX shared module myadd.cp311-win_amd64.pyd [build] Copying runtime dependencies [build] Error copying file "/python312.dll" to "D:/py/build". [build] mingw32-make[2]: *** [CMakeFiles\myadd.dir\build.make:104: myadd.cp311-win_amd64.pyd] Error 1 [build] mingw32-make[2]: *** Deleting file 'myadd.cp311-win_amd64.pyd' [build] mingw32-make[1]: *** [CMakeFiles\Makefile2:82: CMakeFiles/myadd.dir/all] Error 2 [build] mingw32-make: *** [Makefile:90: all] Error 2 [proc] 命令“"C:\Program Files\CMake\bin\cmake.EXE" --build d:/py/build --config Debug --target all -j 24 --”已退出,代码为 2 [driver] 生成完毕: 00:00:01.309 [build] 生成已完成,退出代码为 2 [rollbar] 未处理的异常: 未处理的拒绝承诺: ctest Error: 生成失败。 {}
这是因为gcc
版本太低,经测试gcc 8.1
不能成功编译但是gcc 14
可以
这种情况下python会报错
PS D:\py> python .\test.py Traceback (most recent call last): File "D:\py\test.py", line 1, in <module> import myadd ImportError: DLL load failed while importing myadd: 找不到指定的模块。
这是因为找不到dll。用Process Monitor
查看调用情况如下
可见是c++库的dll找不到。这是因为编译器的lib没有加入PATH
。好的做法是使用静态链接,就像前面说的那样
本文作者:GBwater
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!