C++利用Poco库实现QT的信号与槽效果。
定义信号类
#pragma once
#include "Poco/BasicEvent.h"
#include "Poco/Delegate.h"
#include "Poco/ActiveResult.h"
//通信中使用较多的二进制数组,定义ByteArray进行封装
struct ByteArray
{
char* data;
int length;
};
//使用泛型实现自定义类型的信号数据传递
template <typename T> class Signal
{
public:
Poco::BasicEvent<T> theEvent;
/*
* 发射信号 同步
* T 参数类型
* message 发送数据
*/
void emit(T message)
{
theEvent(this, message);
}
/*
* 发射信号 异步 信号发送同步,事件处理异步
* T 参数类型
* message 发送数据
*/
Poco::ActiveResult<T> emit_Async(T message)
{
return Poco::ActiveResult<T> (theEvent.notifyAsync(this, message));
}
};
//绑定信号与槽
#define Connect(sender, signal, receiver, method) (*sender.signal.theEvent += Poco::delegate(receiver, &method))
//信号与槽解除绑定
#define Disconnect(sender, signal, receiver, method) (*sender.signal.theEvent -= Poco::delegate(receiver, &method))
信号类的使用
需要发送信号的类,引用Signal.h头文件。发送信号携带的参数可以为普通类型,也可以为复杂类型。
定义类型Model
Model.h
#pragma once
class Model
{
private:
/* data */
public:
Model(/* args */);
~Model();
// private:
int a;
int b;
};
Model.cpp
#include "Model.h"
Model::Model(/* args */)
{
}
Model::~Model()
{
}
main头文件引用
#include <iostream>
#include "Signal.h"
#include "Model.h"
#include <thread>
main定义信号发送类
class A
{
public:
Signal<std::string> signal1;
Signal<int> signal2;
Signal<Model> signal3;
};
main定义信号接收类
信号的接收槽函数定义格式为:
void getFromA(const void *pSender, T &message);
T表示参数类型,与信号的参数类型一致,返回值为void。
class B
{
public:
void getFromA(const void *pSender, std::string &message)
{
std::cout << "A says:" << message << " B--ID:" << std::this_thread::get_id() << std::endl;
}
void getIntFromA(const void *pSender, int &message)
{
std::cout << "A says:" << message << " B--ID:" << std::this_thread::get_id() << std::endl;
}
void getModelFromA(const void *pSender, Model &message)
{
std::cout << "A says:" << message.a <<"-"<< message.b<< " B--ID:" << std::this_thread::get_id() << std::endl;
}
};
main主函数
int main(int argc, char **argv)
{
A aDemo;
B bDemo;
std::cout << "mainID:" << std::this_thread::get_id() << std::endl;
Connect(&aDemo, A::signal1, &bDemo, B::getFromA);
Connect(&aDemo, A::signal2, &bDemo, B::getIntFromA);
Connect(&aDemo, A::signal3, &bDemo, B::getModelFromA);
aDemo.signal1.emit_Async("xwss");
aDemo.signal1.emit("bendan");
Poco::ActiveResult<int> Targs = aDemo.signal2.emit_Async(43);
Targs.wait();//阻塞等待线程结束并返回数据
std::cout << "Asyncreturn: " << Targs.data() << std::endl;
aDemo.signal2.emit(10001);
aDemo.signal2.emit_Async(10006);
aDemo.signal1.emit("world hello");
aDemo.signal2.emit(10000);
Model m;
m.a = 1;
m.b = 7;
aDemo.signal3.emit(m);
return 0;
}
需要注意,信号的发送者和接收者槽函数的线程处于同一个线程。
绑定信号时,Connect(sender, signal, receiver, method),sender与receiver为对象的指针。接收者使用this指向类本身的实例化对象会报错(QT支持该写法)。
引用的Poco库
另外,该方法的使用需要引入Poco的PocoFoundationd库。
参考资源
基于ubuntu16.04编译的Poco库:https://download.csdn.net/download/qq_40778196/87716080
C++利用Poco库实现QT的信号与槽效果完整工程:https://download.csdn.net/download/qq_40778196/87716091