如何用Boost.Python向Python暴露C++变量并在循环中实时更新?
咱们先来拆解下你遇到的问题:你拿到<property object>是因为你访问的是类的属性,而不是类的实例!cbtest.callback_handler是Python中的类对象,gui_cancel是Boost.Python为这个类创建的属性描述符,只有当你拿到这个类的实际实例时,访问gui_cancel才能获取到C++端的真实变量值。
下面给你两种可行的实现方案,分别适配轮询获取和主动通知的场景:
方案1:通过实例访问实现实时轮询
这个方案适合Python端需要主动周期性检查C变量的场景,核心是确保Python拿到的是C中callback_handler的实际实例,而不是类本身。
步骤1:修改C++代码暴露实例
首先在C++中提供一个获取全局/单例callback_handler实例的函数,并通过Boost.Python暴露:
#include <boost/python.hpp> using namespace boost::python; class callback_handler : boost::noncopyable { public: bool gui_cancel = false; // 这里可以添加你GUI更新var4/gui_cancel的逻辑 }; // 提供全局实例的访问入口(单例模式) callback_handler& get_callback_instance() { static callback_handler instance; return instance; } BOOST_PYTHON_MODULE(cbtest) { class_<callback_handler, boost::noncopyable>("callback_handler", no_init) .def_readwrite("gui_cancel", &callback_handler::gui_cancel); // 暴露获取实例的函数,注意返回引用避免拷贝 def("get_callback_instance", &get_callback_instance, return_value_policy<reference_existing_object>()); }
步骤2:Python端访问实例获取实时值
现在Python代码中要先获取实例,再访问变量,这样每次访问都会直接读取C++端的最新值:
import cbtest import time # 获取C++端的callback_handler实例,而不是类 handler = cbtest.get_callback_instance() # 测试初始值 print(f"初始gui_cancel值: {handler.gui_cancel}") # 循环实时检查更新(模拟你的业务逻辑) while True: current_val = handler.gui_cancel if current_val: print("检测到GUI取消信号,退出循环") break print(f"当前gui_cancel值: {current_val}") time.sleep(0.1) # 加延迟避免CPU占用过高
方案2:通过回调函数实现主动通知
如果需要C++端变量更新时主动通知Python(而不是Python轮询),可以给callback_handler添加回调函数成员,让Python注册回调逻辑。
步骤1:修改C++代码支持回调
#include <boost/python.hpp> #include <functional> using namespace boost::python; class callback_handler : boost::noncopyable { public: bool gui_cancel = false; // 定义回调函数类型 std::function<void(bool)> on_cancel_updated; // 假设GUI更新时会调用这个方法来更新变量并触发回调 void update_gui_cancel(bool new_val) { gui_cancel = new_val; // 如果Python注册了回调,就触发它 if (on_cancel_updated) { on_cancel_updated(new_val); } } }; callback_handler& get_callback_instance() { static callback_handler instance; return instance; } BOOST_PYTHON_MODULE(cbtest) { class_<callback_handler, boost::noncopyable>("callback_handler", no_init) .def_readwrite("gui_cancel", &callback_handler::gui_cancel) .def_readwrite("on_cancel_updated", &callback_handler::on_cancel_updated); def("get_callback_instance", &get_callback_instance, return_value_policy<reference_existing_object>()); }
步骤2:Python端注册回调
import cbtest # 定义回调逻辑,C++端更新时会自动调用 def handle_cancel_update(new_val): print(f"GUI取消状态已更新: {new_val}") if new_val: print("执行取消相关的业务逻辑...") # 获取实例并注册回调 handler = cbtest.get_callback_instance() handler.on_cancel_updated = handle_cancel_update # 保持Python进程运行(根据你的实际业务场景调整) import time while True: time.sleep(1)
关键误区说明
你之前的代码holder = cbtest.callback_handler; print(holder.gui_cancel)中,holder是Python的类对象,不是C类的实例,所以gui_cancel是Boost.Python生成的属性描述符(即<property object>),只有访问实例的gui_cancel才能拿到C端的实际变量值,而且因为是直接引用内存,C++端更新后Python端能实时读取到最新值。
内容的提问来源于stack exchange,提问作者Karls




