• boost之signal的使用


    简介

    boost是C++的一个扩展库,被称为C++准标准库,里面的组件很丰富,并且引用方便,85%的组件只需要引用头文件即可使用。

    并且在嵌入式系统也可以很方便的使用,这里介绍一下signal的使用,有点类似Qt里的信号槽。
    可以接收静态函数、类成员函数、labmda表达式。

    下面这个是使用signal封装的一个事件注册处理模板,使用起来还是很方便的。

    代码

    模板实现:
    #ifndef __EVENT_PROC_H__
    #define __EVENT_PROC_H__
    #include <iostream>
    #include <map>
    #include <string>
    #include <boost/bind.hpp>
    #include "boost/signals2.hpp"
    
    using namespace std;
    
    
    #ifndef RTN_FAIL
    #define RTN_FAIL -1
    #endif
    
    #ifndef RTN_SUCCESS
    #define RTN_SUCCESS 0
    #endif
    
    
    
    /*----------------------------------类定义-----------------------------------*/
    template <typename TypeEvent, typename TypeFunc ,typename TypeFnData, typename TypeFnDataLen>
    class TSEventProc
    {
    public:
        TSEventProc() {}
        ~TSEventProc() {}
        int RegEvent(TypeEvent tpEvent, TypeFunc func);   // 注册处理函数
        int ProcEvent(TypeEvent tpEvent, TypeFnData tpData, TypeFnDataLen tpDataLen);  // 处理指令数据
    
        typedef boost::signals2::signal<void(TypeEvent,TypeFnData, TypeFnDataLen)> EventSignal;
        
    protected:
        map< TypeEvent, EventSignal*> m_mpEventProcMap;   // 命令字与处理函数映射表
    };
    
    
    /*----------------------------------类实现-----------------------------------*/
    //事件注册
    template <typename TypeEvent,typename TypeFunc, typename TypeFnData, typename TypeFnDataLen>
    int TSEventProc< TypeEvent, TypeFunc,TypeFnData, TypeFnDataLen>::RegEvent(TypeEvent tpEvent, TypeFunc func)
    {
        typename map< TypeEvent, EventSignal* >::iterator iter = m_mpEventProcMap.find(tpEvent);
        if( iter != m_mpEventProcMap.end() )
        {
            iter->second->connect(func);
        }
        else
        {
            m_mpEventProcMap[tpEvent] = new EventSignal;
            m_mpEventProcMap[tpEvent]->connect(func);
        }
    
        return RTN_SUCCESS;
    }
    
    //事件处理
    template <typename TypeEvent, typename TypeFunc,typename TypeFnData, typename TypeFnDataLen>
    int TSEventProc<TypeEvent, TypeFunc,TypeFnData, TypeFnDataLen>::ProcEvent(TypeEvent tpEvent, TypeFnData tpData, TypeFnDataLen tpDataLen)
    {
        EventSignal *pEventSignal = NULL;
        typename map< TypeEvent, EventSignal*>::iterator iter = m_mpEventProcMap.find(tpEvent);
        if(iter != m_mpEventProcMap.end())
        {
            pEventSignal = iter->second;
            (*pEventSignal)(tpEvent,tpData,tpDataLen);
        }
        else
        {
            cout<<"in ProcEvent, Can't find cmd ["<<tpEvent<<"] process function."<<endl;
            return RTN_FAIL;
        }
    
        return RTN_SUCCESS;
    }
    
    
    #endif /* __EVENT_PROC_H__ */
    
    
    
    测试代码
    #include <QCoreApplication>
    #include <iostream>
    
    using namespace std;
    
    #include "event_proc.h"
    #include "boost/bind.hpp"
    
    typedef boost::function<void(string, const void *, int)>  MSG_FUNCTION3;
    
    //测试用的处理函数
    void TestCmd(string event,const void * pData, int iLen)
    {
        char *pcData = (char *)pData;
        cout<<"TestCmd: event: "<<event<<endl;
    
        if (pcData)
            printf("dev: %d, cmd: %d,dataLen: %d
    ", pcData[0], pcData[1],iLen);
        return;
    }
    
    //测试用的处理函数
    void TestCmd1(string event,const void * pData, int iLen)
    {
        char *pcData = (char *)pData;
        cout<<"TestCmd1: event: "<<event<<endl;
    
        if (pcData)
            printf("dev: %d, cmd: %d,dataLen: %d
    ", pcData[0], pcData[1],iLen);
        return;
    }
    
    //测试用类
    class testFuncObject
    {
    public:
        void TestFunc(string event,const void * pData, int iLen)
        {
            cout<<"testFuncObject::TestFunc: event: "<<event<<endl;
    
            char *pcData = (char *)pData;
            if (pcData)
                printf("testFuncObject::TestFunc, dev: %d, cmd: %d,dataLen: %d
    ", pcData[0], pcData[1],iLen);
        }
    };
    
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        TSEventProc <string, MSG_FUNCTION3,const void*, int> eventMgr;
        char Data[32] = {0};
    	
    	//使用静态函数
        eventMgr.RegEvent("event1",TestCmd);
        eventMgr.RegEvent("event1",TestCmd1);
        eventMgr.RegEvent("event2",TestCmd);
    
        //使用lambda表达式
        eventMgr.RegEvent("event2",[](string event,const void * pData, int iLen){
            cout<<"use labmda: event: "<<event<<endl;
        });
    
        //测试使用类成员函数
        testFuncObject testobj;
        eventMgr.RegEvent("event2",boost::bind(&testFuncObject::TestFunc, &testobj, _1,_2,_3));
    
    
        Data[0] = 31;
        Data[1] = 2;
        //event1事件处理
        eventMgr.ProcEvent("event1", Data, (int)sizeof(Data)); 
        Data[1] = 3;
        //event2事件处理
        eventMgr.ProcEvent("event2", Data, (int)sizeof(Data));
    
        return a.exec();
    }
    
    

    上面测试代码是在qt的工程里写的,所以有 QCoreApplication a(argc, argv); 和 a.exec();

    运行结果
    TestCmd: event: event1
    dev: 31, cmd: 2,dataLen: 32
    TestCmd1: event: event1
    dev: 31, cmd: 2,dataLen: 32
    TestCmd: event: event2
    dev: 31, cmd: 3,dataLen: 32
    use labmda: event: event2
    testFuncObject::TestFunc: event: event2
    testFuncObject::TestFunc, dev: 31, cmd: 3,dataLen: 32
    
  • 相关阅读:
    入门(一)---Java的发展史
    移除元素
    TCP的 “三次握手” 和“四次挥手”,到底是什么鬼?
    功能测试框架
    python学习笔记之--__new__方法和__init__方法
    HTTP协议状态码详解
    python学习笔记之--hasattr函数
    一文总结软件测试工程师面试前必背的面试题(持续更新中)
    MYSQL安装file /usr/share/mysql/charsets/README from install of MySQL-server-5.6.35-1.el6.x86_64 conflicts with file from package mariadb-libs-1:5.5.60-1.el7_5.x86_64报错
    centos7 安装salt起不来处理
  • 原文地址:https://www.cnblogs.com/fensnote/p/13436455.html
Copyright © 2020-2023  润新知