sigslot库--一个简单的C++消息框架

目录

 

总体思路:

简介:

使用场景:

使用方法:

实例:


总体思路:

sig---信号

slot---插槽

信号.connect(&插槽对象,&插槽类::插槽类成员函数)

简介:

信号/插槽机制:A对象声明一个信号(sig),B对象实现对应参数的插槽(slot),将他们连接起来(connect),当A对象触发带上参数的信号时,B对象所连接的函数就会相应。有点像回调。

和回调的区别:

  1. 回调是个函数指针,缺点有两个,一是类型不安全,你不知道使用者调用回调的对象和参数是否正确;二是过于耦合,处理函数通常要和回调函数一起。

  2. 信号插槽机制优点:一是不用担心空指针,插槽对象析构时,会自动断开连接(disconnect);二是线程安全,带锁,不用担心多线程之间的冲突。当然缺点也有,没有返回值即只能是void函数,而且顺序不能调整插槽对象的响应先后。

使用场景:

     两个独立的对象或者模块之间,想要直接沟通,但是又不想过多暴露接口,如果联系比较简单,这时可以考虑这个轻量级的消息框架---sigslot,整个库就一个头文件sigslot.h,集成非常灵活。

使用方法:

  1. sig声明时指定参数列表,参数个数是0-8个

  2. slot类必须继承has_slots<>,slot函数必须是void返回值,参数列表和sig声明一样。

  3. 常用函数:connect、disconnect、disconnect_all

实例:

    抽象一个Sender类作为sig,抽象一个Receiver类作为slot,实例中有两种常用用法,第一种是模拟两个独立模块建立一个简单连接,第二种是模拟Receiver作为Sender类相关的嵌入模块。

    0.辅助头文件

#ifndef __SIGSLOT_BASEDEFINE_H__
#define __SIGSLOT_BASEDEFINE_H__

#define MAX_NAME_LENGTH 32

typedef struct Info_ {
  int num;
  char name[MAX_NAME_LENGTH];
} Info;

typedef struct Message_ {
  int msgid;
  Info info;
} Message;


#endif // __SIGSLOT_BASEDEFINE_H__

    1.sig----Sender类

// sender.h
#ifndef __SIGSLOT_SENDER_H_
#define __SIGSLOT_SENDER_H_
#include "sigslot.h"
#include "receiver.h"

class Sender {
 private:
  int id;
 public:
  Sender();
  ~Sender();

  sigslot::signal1<Message *> SendMessage;

  int broadcast(Info &info);
  bool addReceiver(Receiver *);
};

#endif // __SIGSLOT_SENDER_H_
//sender.cpp
#include "sender.h"
#include <cstring>

Sender::Sender(/* args */): id(0) {
}

Sender::~Sender() {
}

int Sender::broadcast(Info &info) {
  Message msg;
  msg.msgid = id++;
  msg.info.num = info.num;
  strncpy(msg.info.name, info.name, MAX_NAME_LENGTH);
  
  SendMessage(&msg);
  return 0;
}

bool Sender::addReceiver(Receiver *new_receiver) {
  SendMessage.connect(new_receiver, &Receiver::onMessage);
  return true;
}

    2.slot----Receiver类

// receiver.h
#ifndef _SIGSLOT_RECEIVER_H_
#define _SIGSLOT_RECEIVER_H_

#include "sigslot.h"
#include "basedefine.h"
#include <iostream>

class Receiver: public sigslot::has_slots<> {
 private:
  std::string m_name;

 public:
  Receiver();
  Receiver(std::string name);
  ~Receiver();

  void onMessage(Message *msg);
};

#endif // _SIGSLOT_RECEIVER_H_
//sender.cpp
#include "receiver.h"

Receiver::Receiver() {

}

Receiver::Receiver(std::string name): m_name(name) {

}

Receiver::~Receiver() {

}

void Receiver::onMessage(Message *msg) {
  printf("[%s:%d] --> %s get message, num:%d name:%s \n",
         __FUNCTION__, __LINE__, m_name.c_str(),msg->info.num, msg->info.name);
}

   3.测试用例

//test_sigslot.cpp
#include "basedefine.h"
#include "receiver.h"
#include "sender.h"
#include <cstring>

int main(int argc, char const *argv[]) {
  Receiver receiver1("receiver1");
  Sender sender;
  // 1.模拟两个独立的模块建立连接
  sender.SendMessage.connect(&receiver1, &Receiver::onMessage);

  // 2.模拟Receiver模块作为Sender模块相关的嵌入模块
  //   通过开放接口建立连接,隐藏内部两个模块之间交互细节
  Receiver receiver2("receiver2");
  sender.addReceiver(&receiver2);
  Receiver receiver3("receiver3");
  sender.addReceiver(&receiver3);
  Receiver *p_receiver4 = new Receiver("receiver4");
  sender.addReceiver(p_receiver4);

  //test sender send msg
  Info info;
  info.num = 4869;
  strncpy(info.name, "miaopasi", MAX_NAME_LENGTH);
  printf("[%s:%d] --> send msg after add r1,r2,r3 \n", __FUNCTION__, __LINE__);
  sender.broadcast(info);

  // 主动断开r2的连接
  sender.SendMessage.disconnect(&receiver2);
  // 销毁r4,sigslot内部会被动断开连接
  if (p_receiver4) {
    delete p_receiver4;
    p_receiver4 = NULL;
  }
  printf("[%s:%d] --> send msg after disconnet r2 and destory r4 \n", __FUNCTION__, __LINE__);
  sender.broadcast(info);

  // 断开所有连接
  sender.SendMessage.disconnect_all();
  printf("[%s:%d] --> send msg after disconnet all \n", __FUNCTION__, __LINE__);
  sender.broadcast(info);

  return 0;
}

问题:

    1)GCC编译时遇到继承has_slots<>时,提示typename问题。

         用到的const_iterator是个模板,需要前提声明typename,自己改起来会很麻烦。建议参考https://www.cnblogs.com/choday/p/3429975.html的头文件。

       sigslot.h

 

参考:https://blog.csdn.net/business122/article/details/80988373

          https://www.cnblogs.com/kanego/articles/sigslot.html

          http://sigslot.sourceforge.net/

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值