如何用PyBind11将C++类转为Python可用数据类型并支持回调?
用pybind11绑定C++自定义类并实现Python回调
1. 基础C++类绑定到Python
先定义你的C++ Dog 类,再通过pybind11将其暴露为Python可调用的类:
C++ 侧代码
#include <string> #include <iostream> #include <pybind11/pybind11.h> namespace py = pybind11; // 自定义C++类 class Dog { private: std::string name; public: Dog(std::string n) : name(std::move(n)) {} void bark() const { std::cout << name << " says: Woof!" << std::endl; } std::string get_name() const { return name; } }; // 绑定模块 PYBIND11_MODULE(myextension, m) { // 将Dog类绑定到Python模块,类名为"Dog" py::class_<Dog>(m, "Dog") .def(py::init<std::string>()) // 暴露构造函数(接收字符串参数) .def("bark", &Dog::bark) // 暴露bark方法 .def("get_name", &Dog::get_name); // 暴露get_name方法 }
编译后,Python中可直接使用该类:
import myextension # 创建Dog实例 my_dog = myextension.Dog("Buddy") # 调用类方法 my_dog.bark() # 输出: Buddy says: Woof! print(my_dog.get_name()) # 输出: Buddy
2. 实现Python回调接收C++类实例
要让Python回调函数接收Dog实例,C++侧只需直接传递对象给Python可调用对象,pybind11会自动处理类型转换。
C++ 侧新增回调触发函数
在绑定模块中添加触发回调的函数,将Dog实例传递给Python回调:
// 触发Python回调的函数 void trigger_dog_callback(py::object callback) { // 创建一个Dog实例 Dog max_dog("Max"); // 直接将Dog实例传入Python回调 callback(max_dog); } // 更新模块绑定 PYBIND11_MODULE(myextension, m) { py::class_<Dog>(m, "Dog") .def(py::init<std::string>()) .def("bark", &Dog::bark) .def("get_name", &Dog::get_name); // 绑定触发回调的函数 m.def("trigger_dog_callback", &trigger_dog_callback, "Pass a Dog instance to Python callback"); }
Python 侧定义回调函数
直接定义接收myextension.Dog类型的函数,调用其方法:
import myextension def make_dog_bark(dog): // 验证参数类型 if isinstance(dog, myextension.Dog): print(f"Making {dog.get_name()} bark...") dog.bark() // 调用C++侧函数,传入回调 myextension.trigger_dog_callback(make_dog_bark)
运行后输出:
Making Max bark... Max says: Woof!
关键注意事项
- 与
vector转py::array的手动转换不同,自定义类的实例传递由pybind11自动处理,无需手动序列化/转换。 - 如果C++侧传递的是动态分配的
Dog指针(比如new Dog("Max")),需要指定所有权策略避免内存泄漏:
这样Python会负责管理该对象的内存。callback(py::cast(new Dog("Max"), py::return_value_policy::take_ownership));
内容的提问来源于stack exchange,提问作者Tommy Wolfheart
相关产品推荐
相关产品推荐

