C++ Boost сигналы и соединение слотов
Я пытаюсь подключить графический интерфейс к своему логическому потоку, используя повышающие сигналы и слоты, у логического класса есть удобный метод для подключения функций к сигналу. Вот упрощенная копия класса locig:
#include <boost/signals2.hpp>
#include <boost/function.hpp>
typedef boost::signals2::signal<void (const double&)> some_signal;
typedef some_signal::slot_type some_slot;
class LogicClass {
some_signal sig;
public:
LogicClass();
~LogicClass();
void register_callback(boost::function<void (const double&)>) {
sig.connect(boost::bind(&LogicClass::doStuff(), this, _1));
}
void doStuff(); // Does a bunch of stuff in a separate thread and fires LogicClass::sig every now and then
}
Вот упрощенная копия класса GUI
#include <boost/signals2.hpp>
#include <QWidget.h>
class GuiClass : public QWidget {
Q_OBJECT //etc. etc. w.r.t. Qt stuff
public:
GuiClass ();
~GuiClass ();
void draw_stuff(const double&); // Want this to listen to LogicClass::sig;
}
В какой-то момент в моем коде класс gui уже создан, а класс логики - нет. Поэтому я хочу создать экземпляр LogicClass и подписаться на GuiClass::draw_stuff(const double&)
к LogicClass::sig
сигнал. Что-то вроде
#include <logicclass.h>
#include <guiclass.h>
GuiClass *gui; //Was initialized elsewhere, but available here;
void some_function() {
LogicClass *logic = new LogicClass();
logic->register_callback(gui->drawStuff);
logic->do_stuff(); //Start drawing on the gui
delete logic;
}
Это, к сожалению, не работает. Само собой разумеется, что он очень хотел бы работать!
Я знаю, что Qt также реализует сигналы и слоты, но я хотел бы использовать boost для переносимости с другими библиотеками пользовательского интерфейса.
1 ответ
Похоже, вы хотели связать draw_stuff
вместо жестко закодированных doStuff
внутри этой функции регистра:
logic->register_callback(boost::bind(&GuiClass::draw_stuff, gui, _1));
А потом
void register_callback(boost::function<void(double)> handler) {
sig.connect(handler);
}
Простая демонстрация
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/signals2.hpp>
#include <boost/thread.hpp>
#include <iostream>
typedef boost::signals2::signal<void(double)> some_signal;
typedef some_signal::slot_type some_slot;
class LogicClass {
some_signal sig;
public:
LogicClass() = default;
~LogicClass() = default;
void register_callback(boost::function<void(double)> handler) {
sig.connect(handler);
}
void doStuff() {
std::cout << __PRETTY_FUNCTION__ << "\n";
// Does a bunch of stuff in a separate thread and fires LogicClass::sig every now and then
boost::thread([this] {
for (double d : {1,2,3}) {
boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
sig(d);
}
}).join();
}
};
#define Q_OBJECT
struct QWidget {};
class GuiClass : public QWidget {
Q_OBJECT // etc. etc. w.r.t. Qt stuff
public:
GuiClass() = default;
~GuiClass() = default;
void draw_stuff(double v) { std::cout << __PRETTY_FUNCTION__ << "(" << v << ")\n"; }
};
//#include <logicclass.h>
//#include <guiclass.h>
GuiClass *gui; // Was initialized elsewhere, but available here;
void some_function() {
LogicClass *logic = new LogicClass();
logic->register_callback(boost::bind(&GuiClass::draw_stuff, gui, _1));
logic->doStuff(); // Start drawing on the gui
delete logic;
}
int main() {
GuiClass gui_instance;
gui = &gui_instance;
some_function();
}
Печать
void LogicClass::doStuff()
void GuiClass::draw_stuff(double)(1)
void GuiClass::draw_stuff(double)(2)
void GuiClass::draw_stuff(double)(3)