pybind11导出C++类的核心是py::class_<T>(m, "Name").def(py::init<...>())链式调用;必须显式绑定构造函数(如py::init<>()或py::init<int, std::string>()),成员函数需注意返回策略与生命周期语义,模板类须先实例化再绑定,继承需基类派生类均声明init,智能指针应优先用std::make_shared并明确所有权策略。

pybind11导出C++类的基本写法
核心就一行:py::class_ + .def() 链式调用。不需要手写模块初始化函数,也不用管理引用计数——pybind11自动处理。
常见错误是漏掉py::init<>(),导致Python里报TypeError: __init__(): incompatible constructor arguments。只要C++类有公有构造函数,就必须显式绑定,哪怕只是默认构造。
- 用
py::init<>()导出无参构造 - 用
py::init<int, std::string>()导出带参构造,参数类型必须和C++签名严格一致(const std::string&和std::string视为不同) - 如果类含私有/删除的构造函数,又想暴露接口,得用
.def(py::init([](args) { return std::make_unique<T>(args); }))绕过
成员函数、属性和运算符怎么绑
成员函数默认按值传递this,即每次调用都拷贝对象。多数时候你要的是引用语义,得加&或&&说明生命周期——否则Python里修改对象,C++原实例没变,或者访问已销毁对象触发段错误。
-
.def("method", &MyClass::method)→ 拷贝调用,安全但低效 -
.def("method", &MyClass::method, py::return_value_policy::reference)→ 返回引用,适合只读访问 -
.def_readwrite("value", &MyClass::value)绑定公有成员变量;私有成员用.def_property配getter/setter - 重载运算符如
operator+,直接绑&MyClass::operator+,pybind11能自动识别并映射到__add__
模板类、继承和智能指针的坑
模板类不能直接py::class_<MyTemplate<int>>——得先实例化再绑定,比如using IntVec = MyTemplate<int>; py::class_<IntVec>(m, "IntVec")。继承关系要显式声明.def(py::init<>())在基类和派生类里,否则Python无法构造子类。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
立即学习“Python免费学习笔记(深入)”;
返回std::unique_ptr没问题,pybind11自动转成Python对象并接管生命周期;但返回std::shared_ptr时,如果C++侧用new手动分配再包成shared_ptr,容易因Python GC时机和C++析构顺序不一致导致悬垂指针。
- 优先用
std::make_shared构造,避免裸指针中转 - 若类被多个
shared_ptr持有(比如同时被Python和C++线程持有),需确保pybind11绑定时用了py::return_value_policy::reference_internal或明确所有权策略 - 多重继承不支持;虚继承会破坏内存布局,pybind11不保证正确性
编译和链接最容易卡住的点
不是代码写错,而是CMake配置漏项。最常踩的坑是没设CMAKE_CXX_STANDARD 17(pybind11 2.10+ 强制要求C++17),或者没把pybind11头文件路径加进target_include_directories,结果报一堆pybind11/pybind11.h: No such file。
- 用
find_package(pybind11 REQUIRED)后,必须调用pybind11_add_module(yourmod YOUR_SRC.cpp),不能自己写add_library+set_target_properties - Windows下MSVC需额外加
/bigobj,否则模板展开多时链接失败;Clang/GCC要确认-fPIC已启用(动态库必需) - Python找不到模块?检查生成的
.so(Linux)或.pyd(Windows)后缀是否匹配当前Python版本(如cp39对应Python 3.9),名字是否和PYBIND11_MODULE第一个参数一致
.def()都要想清楚“这个Python对象背后,到底谁在管那块内存”。

















