pybind11导出C++类必须显式声明构造函数、成员函数和属性,否则Python不可见;默认不导出私有成员,不自动处理继承;常见错误是遗漏.def(py::init())导致TypeError。

pybind11导出C++类的基本写法
必须显式声明构造函数、成员函数和属性,否则Python里看不到。默认不导出私有成员,也不自动处理继承关系。
常见错误是只写了 py::class_ 模板参数却忘了调用 .def() 绑定构造函数,结果Python报 TypeError: no constructor defined。
- 用
.def(py::init())导出默认构造函数 - 用
.def(py::init<int std::string>())</int>导出带参构造函数(参数类型要和C++签名严格一致) - 成员函数用
.def("name", &MyClass::func),注意取地址符和作用域 - 读写属性用
.def_readwrite("field", &MyClass::field),只读用def_readonly
如何处理C++类中的std::string和std::vector
pybind11默认支持 std::string 和 std::vector<t></t>(其中 T 是基础类型或已绑定类型),但要注意编码和内存所有权。
典型坑:返回局部 std::string 没问题,但返回指向栈上 char* 的 std::string 会引发段错误;std::vector 被拷贝进Python,修改Python端列表不会影响C++原对象。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
立即学习“Python免费学习笔记(深入)”;
- 传入Python
str自动转为std::string(UTF-8解码,不校验) - 返回
std::string自动转为Pythonstr(UTF-8编码) -
std::vector<int></int>可直接映射到Pythonlist,但大数组有拷贝开销 - 如需零拷贝访问,得用
py::array_t<int></int>+py::buffer_info,不是默认行为
导出含虚函数或继承关系的类
pybind11不自动识别虚函数重写,Python子类无法覆盖C++虚函数——除非你手动加 py::dynamic_attr() 并实现 __init__ 中的钩子,但这很脆弱。
更实际的做法是:把需要被Python继承的基类标记为 py::dynamic_attr(),并在每个虚函数绑定时用 .def("func", [](const MyClass &o) { return o.func(); }) 包一层lambda,强制走虚调用路径。
- 基类必须用
py::class_<base std::shared_ptr>>声明智能指针持有方式 - 派生类绑定前,先确保基类已注册,否则
py::cast<base>(obj)失败 - 避免多重继承,pybind11对C++多继承支持有限,容易触发
RuntimeError: Unable to cast Python instance
编译与链接时最容易漏掉的配置项
不是加了 #include <pybind11></pybind11> 就能跑起来。缺失链接或定义会导致导入模块时报 ImportError: dynamic module does not define module export function 或直接段错误。
- CMake中必须调用
pybind11_add_module(mylib MODULE),不能用普通add_library - 链接时要显式加
target_link_libraries(mylib PRIVATE pybind11::module) - 模块名必须和
PYBIND11_MODULE(mylib, m)第一个参数完全一致(包括大小写) - Linux下生成的文件名必须是
mylib.cpython-*.so,Windows是mylib.pyd,macOS是mylib.cpython-*.dylib;改名或放错目录都会导致ModuleNotFoundError

















