使用pybind11用C++编写python扩展

0.目标

使用C++编写一个模块,让python能够如下调用

基于example.cc这个文件:

1
2
3
4
5
6
7
8
9
10
11
#include <pybind11/pybind11.h>

int add(int i, int j)
{
return i + j;
}

PYBIND11_MODULE(example, m){
m.doc() = "pybind11 example plugin";
m.def("add", &add, "A function which adds two numbers");
}
1
>>>help(example)

1.预备知识(熟悉CMakeLists.txt的编写)

1.1 cmake——强大的项目构建工具

C、C++项目一般用Cmake来进行构建。当编写的源文件越来越多时,一个一个的使用g++ 源文件 -o 输出文件太麻烦了,为此,人们整了个构建工具,它可以根据不同的平台生成不同的项目,这就是Cmake。

1.2 CMAKE_GENERATOR——指定cmake默认生成的项目类型

By default, CMake will use CMAKE_GENERATOR environment variable to determine CMake generator (CMAKE_GENERATOR).

或者在命令行中指定生成的项目类型:

1
2
cmake -G "Visual Studio 15 2017 Win64" ..      
cmake -G "Ninja" ..

Windows下,如果装了VS系列编译器,则cmake默认就会使用vs的编译器并生成32位的项目

  • 如果想让cmake使用MingW 编译器,则添加环境变量CMAKE_GENERATOR,令它的值为MinGW Makefiles.

  • 如果想让cmake使用vs生成64位项目,则添加环境变量CMAKE_GENERATOR,令它的值为Visual Studio 15 2017 Win64.

更多的选项可使用cmake --help查看。

Linux 下

1.pybind11配置

1.1 安装

1
pip3 install pybind11

1.2 使用

使用虚拟环境site-packages/pybind11/include提供的头文件

1
#include <pybind11/pybind11.h>

1.3 额外注意

pybind11本身只含有头文件,很方便。但你需要让编译器知Python.h的位置,并且编译器在链接的过程中会去链接python本身提供的库,譬如python37.lib(根据python版本而定)

  • Linux下就是默认动态链接,一般你安装好了python,一般都会找到

  • Windows下不会,你需要在CMakeLists.txt中明确指定,或者手动敲命令g++ -I头文件目录 -L库目录 -l库名称指定

2.Linux下——生成.so文件

编译命令

1
g++ -O3 -Wall -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` example.cc -o example`python3-config --extension-suffix`

python3-config是一个脚本,很有用,可以得到一些前缀、后缀等信息,Linux下特有,Windows下没有!!!

3.Window——生成.dll文件,但是!

但是需要将后缀改为.pyd, python才认,不然就报ModuleNotFoundError错误!!

  • example.pyd

  • example.cp37-win_amd64.pyd

According to Python3 default settings, the full extension of the compiled C++ file under Windows has to be .cp37-win_amd64.pyd.

We can get the extension by terminal command:

1
python -c "from distutils import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))"

That is an equivalent of the python3-config --extension-suffix from pybind11 documentation. The python3-config script is not implemented in Windows environment .

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
cmake_minimum_required(VERSION 3.12)
project(MyProject VERSION 1.0.0)


include_directories("./env/Lib/site-packages/pybind11/include")
include_directories("D:/SDK/python37/include")

link_directories("D:/SDK/python37/libs")

link_libraries(python37)

add_library(example SHARED ./example.cc)
文章作者: 小王同学
文章链接: https://morvan.top/2021/09/24/使用pybind11用C-编写python扩展/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 小王同学的精神驿站