c++如何与Python交互 c++ pybind11框架使用【教程】

Pybind11是轻量易用的C++/Python绑定库,支持函数导出、STL类型自动转换、NumPy零拷贝及跨平台构建,无需Python C API知识。

用 C++ 写高性能模块,再用 Python 调用,是工业级项目的常见做法。Pybind11 是目前最轻量、易上手且功能完备的 C++/Python 绑定库,无需 Python C API 底层知识,编译即用。

一、安装与最小可运行示例

推荐用 pip 安装 pybind11(头文件库,无运行时依赖):

pip install pybind11

写一个最简 C++ 函数并暴露给 Python:

// example.cpp
#include 

int add(int a, int b) { return a + b; }

PYBIND11_MODULE(example, m) { m.doc() = "pybind11 example plugin"; m.def("add", &add, "A function that adds two integers"); }

用 pybind11 提供的 setup.py 编译(需已安装 C++ 编译器,如 g++/MSVC):

from pybind11.setup_helpers import Pybind11Extension
from setuptools import setup

ext_modules = [ Pybind11Extension("example", ["example.cpp"]), ]

setup( name="example", ext_modules=ext_modules, )

终端执行:python setup.py build_ext --inplace,生成 example.cpython-*.so(Linux/macOS)或 .pyd(Windows)文件,即可在 Python 中导入使用:

import example
print(example.add(3, 4))  # 输出:7

二、传递复杂类型:std::vector、字符串、类对象

pybind11 自动支持常见 STL 类型转换(需包含对应头文件):

  • std::vector → Python list(双向自动转换)
  • std::string ↔ str(UTF-8 安全)
  • C++ class 可绑定为 Python 类,支持构造、方法、属性、运算符重载

示例:绑定一个带成员函数的类:

class Pet {
public:
    Pet(const std::string &name) : name_(name) {}
    void set_name(const std::string &n) { name_ = n; }
    const std::string &get_name() const { return name_; }
private:
    std::string name_;
};

PYBIND11MODULE(pet, m) { pybind11::class(m, "Pet") .def(pybind11::init()) .def("set_name", &Pet::set_name) .def("get_name", &Pet::get_name); }

Python 端调用:

from pet import Pet
p = Pet("Milo")
p.set_name("Luna")
print(p.get_name())  # Luna

三、处理 NumPy 数组(高效数据交换)

科学计算场景下,避免拷贝大数组是关键。pybind11 支持零拷贝访问 NumPy 数组:

  • 需安装 numpy 并在 C++ 中 #include
  • pybind11::array_t 接收数组,通过 .data() 获取原始指针
  • 支持 shape、stride、dtype 检查,确保内存布局安全

示例:对 float32 数组做原地加法:

void add_one(pybind11::array_t arr) {
    auto buf = arr.request();
    float *ptr = static_cast(buf.ptr);
    for (size_t i = 0; i < buf.size; ++i) {
        ptr[i] += 1.0f;
    }
}

// 绑定 m.def("add_one", &add_one);

Python 端传入 numpy.ndarray 即可,底层不复制内存。

四、构建与跨平台注意事项

pybind11 本身是纯头文件库,但构建仍需注意:

  • Linux/macOS 默认用系统 clang/g++;Windows 推荐 MSVC 2019+ 或 Clang-cl
  • 若项目已有 CMake,直接用 find_package(pybind11 REQUIRED),更稳定可控
  • 发布时,扩展模块需与目标 Python 版本 ABI 兼容(建议用 auditwheeldelvewheel 修复依赖)
  • 调试崩溃时,开启 -g 编译选项,并用 gdb python -c "import yourmod" 定位 C++ 层问题

不复杂但容易忽略:确保 Python 解释器与编译时链接的 libpython 一致(尤其在 conda/virtualenv 多环境时)。