pybind11基础教程:从零开始构建Python C++扩展
前言
pybind11是一个轻量级的C++库,用于将C++代码暴露给Python调用。它通过模板元编程技术实现了Python和C++之间的无缝互操作,大大简化了创建Python扩展模块的过程。本文将带你了解pybind11的基础使用方法。
环境准备
在开始使用pybind11前,需要确保开发环境已正确配置。
Linux/macOS环境
需要安装以下依赖:
- Python开发头文件(python-dev或python3-dev)
- CMake构建工具
安装完成后,可以通过以下命令编译测试用例:
mkdir build
cd build
cmake ..
make check -j 4
Windows环境
Windows上需要Visual Studio 2017或更高版本。编译命令如下:
mkdir build
cd build
cmake ..
cmake --build . --config Release --target check
注意:如果所有测试都失败,请检查Python二进制文件和测试用例是否针对相同的处理器架构(i386或x86_64)编译。
基础用法
头文件与命名空间
所有pybind11代码都应包含以下头文件和命名空间别名:
#include <pybind11/pybind11.h>
namespace py = pybind11;
重要提示:pybind11/pybind11.h
会自动包含Python.h
,因此它必须是任何源文件或头文件中第一个被包含的文件。
创建简单函数绑定
让我们从一个简单的加法函数开始,展示如何将其暴露给Python:
int add(int i, int j) {
return i + j;
}
PYBIND11_MODULE(example, m) {
m.doc() = "pybind11示例插件"; // 可选的模块文档字符串
m.def("add", &add, "一个将两个数字相加的函数");
}
PYBIND11_MODULE
宏创建了一个Python模块,m.def()
方法将C++函数注册为Python可调用的函数。
编译模块
pybind11是仅头文件的库,不需要链接特殊库。在Linux上可以使用以下命令编译:
c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3 -m pybind11 --extension-suffix)
编译完成后,可以在Python中直接导入使用:
import example
print(example.add(1, 2)) # 输出3
进阶特性
关键字参数
可以通过py::arg
指定参数名称,使Python端可以使用关键字参数调用:
m.def("add", &add, "一个将两个数字相加的函数",
py::arg("i"), py::arg("j"));
Python调用方式:
example.add(i=1, j=2)
更简洁的写法是使用字面量:
using namespace pybind11::literals;
m.def("add", &add, "i"_a, "j"_a);
默认参数
对于有默认参数的C++函数,可以这样暴露:
int add(int i = 1, int j = 2) {
return i + j;
}
m.def("add", &add, "一个将两个数字相加的函数",
py::arg("i") = 1, py::arg("j") = 2);
导出变量
可以将C++中的值导出为Python模块属性:
PYBIND11_MODULE(example, m) {
m.attr("the_answer") = 42;
py::object world = py::cast("World");
m.attr("what") = world;
}
Python中使用:
print(example.the_answer) # 42
print(example.what) # 'World'
支持的数据类型
pybind11支持大量数据类型在C++和Python之间自动转换,包括但不限于:
- 基本类型(int、float等)
- STL容器(vector、map等)
- 自定义类
- 函数对象
- 智能指针
具体支持的类型列表可以参考pybind11的进阶文档。
总结
本文介绍了pybind11的基础使用方法,包括:
- 环境配置和模块编译
- 简单函数绑定
- 关键字参数和默认参数处理
- 变量导出
- 支持的数据类型
pybind11通过简洁的API大大简化了创建Python扩展的过程,让开发者可以专注于业务逻辑而非接口转换的细节。对于更复杂的使用场景,pybind11还提供了许多高级特性,如类绑定、异常处理等,这些将在后续文章中介绍。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考