pybind11简介
- pybind11是一个轻量级仅使用头文件包含的python库,它允许用户在python中公开C++类型,也同样支持在C++公开python的类型,主要用作在python中导入C++现有的代码。
- 一个简单的说明就是我们可以通过pybind11在C++或者python中使用对方语言中的类型,函数(包括用户自定义的类型及函数)
在conda中安装pybind11
- 推荐在conda虚拟环境下进行安装
- 关于linux下如何安装Anaconda可以参考这一篇文章:https://blog.csdn.net/2301_79485441/article/details/135269525
- 创建虚拟环境并下载pybind11
- 创建环境,your_env_name为你要给该虚拟环境取的名字,这里推荐py版本为3.8
conda create --name your_env_name python=3.8
- 激活环境并下载pybind11
source activate your_env_name conda install -c conda-forge pybind11
- 创建环境,your_env_name为你要给该虚拟环境取的名字,这里推荐py版本为3.8
使用指南(Linux)
在python中导入C++函数
- 创建一个example.cpp文件用于编写待转换的C++函数
#include <pybind11/pybind11.h> namespace py = pybind11; int add(int i, int j) { return i + j; } PYBIND11_MODULE(example, m) { m.doc() = "pybind11 example plugin"; m.def("add", &add, "A function that adds two numbers",py::arg("i")=1, py::arg("j")=2); }
- 上述实例代码中,PYBIND11_MODULE宏指令创建了一个module(名字为example),并通过m.def方法绑定指定的C++函数,使这个函数可以在python里被import该model时导入并使用
- example:创建的module的名字
- m:定义了一个类型为py::module_的变量,它是创建绑定的主要接口。
- 其中的方法module_::def()生成绑定代码,将用户指定的函数(这里是add)公开给Python。
- m.def()参数说明:
- “add”:函数名
- &add:绑定C++函数
- “A function that adds two numbers”:添加函数说明,使用户在python使用help(example)时候可以输出对应的帮助信息
help(example)
- py::arg(“i”)=1, py::arg(“j”)=2:添加py的参数对应,使用户在python调用此函数传参时可以通过参数名来指定参数值,同时指定了默认的参数
import example example.add(i=1, j=2)
- 上述实例代码中,PYBIND11_MODULE宏指令创建了一个module(名字为example),并通过m.def方法绑定指定的C++函数,使这个函数可以在python里被import该model时导入并使用
- 编译:
- 由于pybind11是个使用头文件包含的库(header-only library),所以不需要和其他第三方库或者特殊的转换步骤
$ c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
- c++:指定c++编译器
- -03:优化级别的选项(-00,-01,-02,-03),-O3 表示最高级别的优化,以提高程序的执行效率。
- -Wall :告诉编译器打开所有默认的警告。
- -shared:生成共享库(.so文件)
- -std=c++11:编译标准指定C++11
- -fPIC:告诉编译器生成与位置无关的代码(Position Independent Code),这对于共享库是必要的,因为它们需要在不同的地址空间中运行。
- $(python3 -m pybind11 --includes):获取pybind11库所需的头文件和链接路径
- example.cpp:源文件
- -o example$(python3-config --extension-suffix)指定编译器执行库名字example
- 由于pybind11是个使用头文件包含的库(header-only library),所以不需要和其他第三方库或者特殊的转换步骤
- 使用
import example if __name__=='__main__': print(example.add(1,2))
在python中导入C++变量
- 前置步骤和上述相同
- attr函数:在模型内注册C++类型的变量,内置类型和常规对象在指定为属性时会自动转换,并且可以使用函数py::cast显式转换。
- 42!宇宙的答案(不是)
PYBIND11_MODULE(example, m) { m.attr("the_answer") = 42; py::object world = py::cast("World"); m.attr("what") = world; }
- 使用
import example if __name__=='__main__': print(example.the_answer)#输出42 print(example.what)#输出'World'
后续
- 下一篇文章再介绍有关C++面向对象的pybind11使用
参考文章
- https://pybind11.readthedocs.io/en/stable/basics.html
- https://pybind11.readthedocs.io/_/downloads/en/latest/pdf/