通过 pybind11 从 C++ 调用 Python
使用 pybind11 将 C++ 代码封装为 Python 模块
通过 pybind11 从 C++ 调用 Python 是 CoddyKit 上的免费 C++ Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C++ Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C++ Academy 课程共包含 4 节课。
为什么使用 pybind11
pybind11 是一个仅包含头文件的库,可以用极少的样板代码为 C++ 代码创建 Python 绑定。SciPy、TensorFlow 和许多其他项目都在使用它。
最小模块
使用 PYBIND11_MODULE 宏,即可在单个文件中定义 Python 模块。
#include <pybind11/pybind11.h>
namespace py = pybind11;
int add(int a, int b) { return a + b; }
PYBIND11_MODULE(mymodule, m) {
m.def("add", &add, "Add two integers");
}构建模块
请将其构建为 Python 扩展模块——通常使用 CMake 或 setuptools。
# CMake
find_package(pybind11 REQUIRED)
pybind11_add_module(mymodule mymodule.cpp)从 Python 中使用
像使用任何 Python 模块一样导入并使用它。
# Python
import mymodule
print(mymodule.add(2, 3)) # 5公开类
使用 py::class_ 绑定 C++ 类。构造函数、方法和属性都会映射为 Python 中的对应形式。
class Point {
public:
Point(int x, int y) : x_(x), y_(y) {}
int x() const { return x_; }
int y() const { return y_; }
private:
int x_, y_;
};
PYBIND11_MODULE(geom, m) {
py::class_<Point>(m, "Point")
.def(py::init<int, int>())
.def("x", &Point::x)
.def("y", &Point::y);
}类型转换
pybind11 会自动转换常见类型:
std::string↔ Python strstd::vector<T>↔ Python liststd::map↔ Python dict- 数值类型 ↔ Python int/float
NumPy 互操作
请将 NumPy 数组作为 py::array_t<T> 传递。访问缓冲区即可执行零拷贝操作。
void scale(py::array_t<double> arr, double factor) {
auto buf = arr.mutable_unchecked<1>();
for (size_t i = 0; i < buf.size(); ++i)
buf(i) *= factor;
}将 Lambda 用作绑定
如果需要转换参数或包装行为,可以直接绑定 Lambda。
m.def("show", [](const Point& p) {
return "(" + std::to_string(p.x()) + ", " + std::to_string(p.y()) + ")";
});释放 GIL
对于耗时较长的 C++ 计算,请释放 GIL,以便其他 Python 线程运行。
m.def("slow", []() {
py::gil_scoped_release release;
// expensive C++ work, no Python access
});性能
pybind11 只增加极少的开销——每次调用通常为几百纳秒。对于非平凡函数,这一开销可以忽略;但对于被频繁调用且执行成本很低的函数,它会产生影响。
替代方案
其他 Python-C++ 桥接工具:
- Boost.Python——较早出现,开销较大
- SWIG——支持多种语言
- nanobind——较新,速度比 pybind11 更快
实际应用场景
pybind11 非常适合:
- 为 Python 用户封装 C++ 库
- 使用 C++ 代码加速 Python 中的热点路径
- 在 C++ 应用和 Python 工具之间共享数值计算内核
快速检查
pybind11 使用哪个宏来声明 Python 模块?
回顾
使用 pybind11 为 Python 封装 C++ 几乎不需要额外工作。请使用 PYBIND11_MODULE 声明模块,使用 m.def 绑定函数,使用 py::class_ 绑定类。内置转换涵盖 STL 类型;NumPy 数组采用零拷贝方式。
常见问题解答
「通过 pybind11 从 C++ 调用 Python」课时是免费的吗?
是的 — 「通过 pybind11 从 C++ 调用 Python」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C++ Academy 课程的其余内容,请升级到 CoddyKit PRO。 C++ Academy 课程共包含 4 节课。
「通过 pybind11 从 C++ 调用 Python」这节课中我会学到什么?
使用 pybind11 将 C++ 代码封装为 Python 模块 你通过在浏览器中直接运行的动手代码来练习 C++ Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 C++ Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 C++ Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「通过 pybind11 从 C++ 调用 Python」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 C++ Academy 课中编写并运行代码吗?
能。每节 C++ Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- Extern C 与 C ABI
- 通过 pybind11 从 C++ 调用 Python
- 面向 Rust FFI 边界的 C++
- 使用 SWIG 生成多语言绑定