学习pybind11(2):Hello World例子

首先要明白pybind11是干啥的,对于一个C/C++库,可以用pybind11封装它的接口为Python接口,这样得到一个python库,就可以把功能强大的库丢给使用python的boys & girls使用了~

因此,使用pybind11做封装,是我们“library developer”干的事情,说不上底层,但也比较底层了。你应该会用CMake,你也应该熟悉C/C++和Python。你编译出来的python库,其实就是一个.so结尾的动态库,也就是python里的一个module。

现在实现一个add(a, b)的接口,功能是计算两个数字的和。不考虑各种边界情况。

开工:

mkdir -p ~/work/test/toy
cd $_
mkdir 3rdparty
git clone https://github.com/pybind/pybind11 3rdparty/pybind11
mkdir build
mkdir src
touch src/example.cpp
touch CMakeLists.txt

目录结构:


image.png

src/example.cpp

#include 

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

PYBIND11_MODULE(example, m) {
    m.doc() = "pybind11 example plugin"; // optional module docstring

    m.def("add", &add, "A function which adds two numbers");
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.14)

project(toy)

set(CMAKE_CXX_STANDARD 11)

add_subdirectory(3rdparty/pybind11)
pybind11_add_module(example src/example.cpp)

执行构建:

cd build
cmake ..
make
image.png

其中红框里的.so文件就是我们生成的python库了。在python中加载它(盘它!):

python
import example
example.add(100, 200)

example.__doc__
image.png

简要分析说明

这里的CMakeLists.txt中,通过加载pybind11目录,会把pybind11/tools/pybind11Tools.cmake中的pybind11_add_module()函数引入。这个函数的功能,是创建一个指定名字的库(target是一个动态库);但是,会修改库文件名字的前缀后缀;并且还有一堆其他的编译链接设定。因此这里不通过手动add_library()命令来创建target,而是先包含pybind11目录再用pybind11_add_module()函数。

也就是说,pybind11被当成一个3rdparty库被引入当前工程。从代码版本控制的角度看,可以把它弄成一个submodule,当然如果强项作为源码管理也可以,但是要注意tests子目录有3M大,可以考虑删除。

C/C++代码中的exampleCMakeLists.txt中的target名字,要保持一致吗?

是的,要保持一致。譬如把C++中的example改为exampleMod则虽然能编译出库,但是Python中无法import:

image.png

你可能感兴趣的:(学习pybind11(2):Hello World例子)