复用pybind加载的std::function时崩溃问题排查与解决
问题原因及解决方法
崩溃原因
C++端函数存储逻辑缺失+参数传递错误
- 你的
Wrapper类没有定义成员变量来保存传入的累加函数,store_accu_function只是空函数,根本没把函数存下来,后续call_accu_function自然找不到可调用的对象。 - 就算补上存储逻辑,当前
store_accu_function的参数是左值引用,但pybind11传递的是临时生成的std::function包装对象(用来绑定Python方法),函数执行完临时对象就会销毁,后续调用时引用指向的是已释放的内存,直接触发崩溃。
- 你的
Python端类方法定义错误
Accu类的__init__和add_new_output都缺少self参数,这是Python类方法的必备参数,没有的话不仅无法访问实例属性,初始化或调用时就会抛出异常,进一步加剧崩溃问题。
修正后的代码
C++代码
#include <pybind11/pybind11.h> #include <pybind11/functional.h> namespace py = pybind11; class Wrapper { private: // 添加成员变量存储累加函数 std::function<void(const std::string&)> accu_func_; public: Wrapper() = default; // 改为值传递,确保能保存临时对象的副本 void store_accu_function(std::function<void(const std::string&)> accu_function) { accu_func_ = std::move(accu_function); } void call_accu_function(const std::string& x) { // 调用前先检查函数是否有效 if (accu_func_) { accu_func_(x); } } }; PYBIND11_MODULE(PythonModule, module_handle) { py::class_<Wrapper>(module_handle, "LocationFusionWrapper") .def(py::init<>()) .def("store_accu_function", &Wrapper::store_accu_function) .def("call_accu_function", &Wrapper::call_accu_function); }
Python代码
class Accu: # 补上self参数 def __init__(self): self.output = [] # 补上self参数,修正参数名(s改为x更清晰) def add_new_output(self, x: str): self.output.append(x) import PythonModule # 注意类名是LocationFusionWrapper,不是Wrapper c_wrapper = PythonModule.LocationFusionWrapper() accumulator = Accu() c_wrapper.store_accu_function(accumulator.add_new_output) c_wrapper.call_accu_function("x") print(accumulator.output) # 输出: ['x']
关键修正点
- C++端:新增成员变量
accu_func_存储函数,将参数改为值传递(或const引用+拷贝),避免临时对象销毁导致的野引用;调用前检查函数是否有效,防止空调用。 - Python端:给类方法补上
self参数,修正模块和类的调用名称(C++绑定的类名是LocationFusionWrapper)。
内容的提问来源于stack exchange,提问作者Maxime Lucas
相关产品推荐
相关产品推荐

