参考官网文档:https://pybind11.readthedocs.io/en/stable/index.html
一、Pybind11 是什么?
想象你在 Python 里写了个计算器,但跑得太慢,想用 C++ 提速,又不想完全抛弃 Python。Pybind11 就像一座桥,把 C++ 的高性能代码“嫁接”到 Python 里。你可以用 Python 调用 C++ 函数,就像请了个跑得飞快的帮手来干活。
- 主要功能:
- 绑定函数:把 C++ 函数变成 Python 能用的。
- 传递数据:Python 和 C++ 之间无缝传值。
- 扩展模块:生成一个 Python 模块,导入就用。
二、准备工作
-
安装 Pybind11:
- 需要 C++ 编译器(Windows 用 MSVC,Mac/Linux 用 gcc/clang)。
- 用 pip 安装 Pybind11:
- 检查安装:命令行输入 python -m pybind11 --includes,会返回 Pybind11 的头文件路径(比如 -I/…/pybind11/include)。
-
安装 Python 和 CMake:
- 确保有 Python(3.x 推荐)。
- 装 CMake(用来生成项目):pip install cmake 或官网下载。
-
写个简单 C++ 文件: 新建 example.cpp:
int add(int a, int b) {
return a + b;
}
我们要让 Python 能调用这个 add 函数。
三、基础绑定:让 Python 用上 C++
- 改写 C++ 文件: 把 example.cpp 改成这样:
#include <pybind11/pybind11.h>
int add(int a, int b) {
return a + b;
}
PYBIND11_MODULE(example, m) {
m.doc() = "一个简单的加法模块"; // 模块描述
m.def("add", &add, "加两个数", pybind11::arg("a"), pybind11::arg("b"));
}
- #include <pybind11/pybind11.h>:引入 Pybind11 的魔法工具。
- PYBIND11_MODULE(example, m):定义一个 Python 模块叫 example,m 是模块对象。
- m.def:把 C++ 的 add 函数绑定到 Python,起名叫 add,还加了参数名和描述。
-
编译成模块:
- 新建 setup.py:
from setuptools import setup
from pybind11.setup_helpers import Pybind11Extension
ext_modules = [
Pybind11Extension(
"example", # 模块名
["example.cpp"], # 源文件
),
]
setup(
name="example",
ext_modules=ext_modules,
)
-
命令行运行:
python setup.py build_ext --inplace
-
成功后会生成一个 example.xxx.pyd(Windows)或 example.xxx.so(Linux/Mac)。
- 在 Python 中试试:
import example
print(example.add(3, 4)) # 输出 7
print(example.__doc__) # 输出 “一个简单的加法模块”
-
怎么回事?
- Pybind11 把 C++ 代码编译成了 Python 的扩展模块,你可以像导入普通库一样用它。
- 比喻:就像把 C++ 的“快车”装进 Python 的“车库”,随时开出来用。
四、进阶玩法:玩转数据和功能
1. 绑定带默认参数的函数
改 example.cpp:
#include <pybind11/pybind11.h>
int add(int a, int b = 10) {
return a + b;
}
PYBIND11_MODULE(example, m) {
m.def("add", &add, "加两个数", pybind11::arg("a"), pybind11::arg("b") = 10);
}
- 重新编译后:
import example
print(example.add(5)) # 输出 15(5 + 10)
print(example.add(5, 3)) # 输出 8(5 + 3)
2. 处理 Python 列表
让 C++ 处理 Python 传来的列表:
#include <pybind11/pybind11.h>
#include <vector>
std::vector<int> double_list(std::vector<int> lst) {
for (int& x : lst) x *= 2;
return lst;
}
PYBIND11_MODULE(example, m) {
m.def("double_list", &double_list, "把列表每个数翻倍");
}
- 编译后:
import example
print(example.double_list([1, 2, 3])) # 输出 [2, 4, 6]
3. 绑定类
定义一个 C++ 类给 Python 用:
#include <pybind11/pybind11.h>
class Pet {
public:
Pet(const std::string& name) : name(name) {}
void setName(const std::string& new_name) { name = new_name; }
std::string getName() const { return name; }
private:
std::string name;
};
PYBIND11_MODULE(example, m) {
pybind11::class_<Pet>(m, "Pet")
.def(pybind11::init<const std::string&>()) // 构造函数
.def("setName", &Pet::setName) // 方法
.def("getName", &Pet::getName); // 方法
}
- 编译后:
import example
p = example.Pet("小狗")
print(p.getName()) # 输出 “小狗”
p.setName("小猫")
print(p.getName()) # 输出 “小猫”
五、更酷的功能:优化和调试
-
提速:
- Pybind11 默认很快,但可以用 C++ 的优化编译选项(比如 -O3):
python setup.py build_ext --inplace -DCMAKE_CXX_FLAGS="-O3"
- Pybind11 默认很快,但可以用 C++ 的优化编译选项(比如 -O3):
-
调试:
- 出错了?加 --verbose 查看编译详情:
python setup.py build_ext --inplace --verbose
- 出错了?加 --verbose 查看编译详情:
六、实战练习
试试这个任务:
- 写个 C++ 文件 math_ops.cpp:
#include <pybind11/pybind11.h>
int multiply(int a, int b = 2) {
return a * b;
}
PYBIND11_MODULE(math_ops, m) {
m.def("multiply", &multiply, "乘法", pybind11::arg("a"), pybind11::arg("b") = 2);
}
-
用 Pybind11 编译成模块。
-
在 Python 中测试:
import math_ops
print(math_ops.multiply(5)) # 输出 10
print(math_ops.multiply(5, 3)) # 输出 15
七、注意事项
- 编译环境:
- 确保 C++ 编译器版本匹配(比如 MSVC 2019+)。
- 依赖问题:
- 如果用了其他 C++ 库,setup.py 里要加 libraries=[“库名”]。
- 跨平台:
- 编译出的模块只能在同系统用,换系统要重新编译。
八、总结:Pybind11 的绑定法则
- 基础绑定:用 m.def 把 C++ 函数给 Python。
- 高级用法:绑定类(class_)、处理列表(std::vector)。
- 优化调试:加编译选项提速,用 --verbose 查错。
- 打包:用 setup.py 生成模块,导入即用。
通过这个教程,你应该能轻松用 Pybind11 把 C++ 的“超能力”带到 Python 里,像搭积木一样简单!如果有问题欢迎私信交流