Pybind11使用py::keep_alive<1,2>无法保活传入C++的Python对象
问题根源
你的问题核心是Python侧派生的TestEvent实例的生命周期没有和C侧存储的EventPointer正确关联,py::keep_alive<1,2>的配置逻辑没错,但缺少配套的类型绑定配置,且C侧的存储方式没有主动持有Python对象引用:
- 如果你的
EventPointer是std::shared_ptr<Event>,你在绑定Event基类时没有显式指定std::shared_ptr作为持有者类型,pybind不会将C侧的智能指针计数和Python对象的GC引用计数关联,哪怕C侧shared_ptr计数不为0,Python GC还是会回收临时创建的TestEvent实例。 - 你用
keep_alive<1,2>的语义是让EventManager实例(参数1)持有事件对象(参数2)的引用,这种方式会让事件对象的生命周期和EventManager完全绑定,如果事件消费后没有手动解除引用会造成内存泄漏,且如果Event类没有正确绑定多态属性,保活配置不会生效。 - 你C侧队列只存储了
EventPointer(指向基类的智能指针),没有持有Python派生对象的引用,Python GC无法感知C侧还在使用这个对象,会在QueueEvent调用结束后直接回收临时TestEvent实例。
解决方案
步骤1:修正Event基类的绑定配置
绑定基类时显式指定持有者为std::shared_ptr<Event>,如果允许Python继承Event,必须配套实现trampoline类:
// 先实现trampoline类,用于Python派生类的虚函数转发 class PyEvent : public Event { public: using Event::Event; // 重写所有你需要在Python侧实现的虚函数,例如GetEventType EventType GetEventType() const override { PYBIND11_OVERRIDE_PURE(EventType, Event, GetEventType); } }; // 绑定时指定holder和trampoline py::class_<Event, PyEvent, std::shared_ptr<Event>>(m, "Event") .def(py::init<>()) // 其他Event类的方法绑定 ;
步骤2:调整事件存储逻辑,主动持有Python对象引用
如果希望事件消费后自动释放引用,不要依赖keep_alive和EventManager绑定生命周期,直接修改C++侧的队列存储结构,同时保存智能指针和Python对象引用:
// 队列存储类型修改为pair,同时持有事件指针和Python对象引用 std::queue<std::pair<EventPointer, py::object>> mEventQueue; void EventManager::QueueEvent(const EventPointer pEvent) { auto _foundList = mEventListenersDelegatesMap.find(pEvent->GetEventType()); if (_foundList != mEventListenersDelegatesMap.end()){ // 构造时自动增加Python对象的引用计数 mEventQueue.Push(std::make_pair(pEvent, py::cast(pEvent))); return; } } // 消费事件的逻辑,消费完成后pair销毁自动减少引用计数 void ProcessEventQueue() { while(!mEventQueue.empty()) { auto [pEvent, pyRef] = mEventQueue.front(); mEventQueue.pop(); // 执行事件触发逻辑 TriggerEvent(pEvent); // 函数退出后pyRef销毁,自动解除Python对象引用 } }
步骤3:优化绑定配置(可选)
如果还是要使用keep_alive,给方法显式指定参数名,避免索引错位:
.def("TriggerEvent", &EventManager::TriggerEvent, py::arg("pEvent"), py::keep_alive<1, 2>()) .def("QueueEvent", &EventManager::QueueEvent, py::arg("pEvent"), py::keep_alive<1, 2>())
内容的提问来源于stack exchange,提问作者user3193075
相关产品推荐
相关产品推荐

