信号槽库:sigslot.h和sigc++使用

  1. sigslot库
    1. 官方地址
    2. 在vs2013中使用
    3. 基本使用:
    4. 实例:
  2. sigc++库
    1. 官方地址
    2. 编译
    3. 在vs中使用
    4. 基本使用:
    5. 实例:

用qt的知道,qt有方便简单的信号槽机制,但需要专门的qt工具处理。
如果想直接使信号槽就可以使用sigslot库,或者sigc++库,或者boost中的signals,这里介绍sigslot和sigc++库。

sigslot.h:只有一个头文件,使用简单方便。
sigc++:包含文件多,但功能更强大。


sigslot库

官方地址

http://sigslot.sourceforge.net/

在vs2013中使用

  • 包含头文件
#include "sigslot.h"
  • 改动:
    //在sigslot.h的420,将:
typedef sender_set::const_iterator const_iterator;
    //改为:
typedef typename sender_set::const_iterator const_iterator;

基本使用:

  • signal0~signal8:信号类:作为类成员
    class mySg
    {
        sigc::signal0<>                 sg1;    // 无参数
        sigc::signal2<char*, double>    sg2;    // 2个参数
    }
  • connection
    槽函数:作为类成员,类需要继承has_slots<>,且槽函数的返回值必须是void类型
    class mySlot: public : has_slots<>
    {
    public:
        void on_func1(){}						
            // 无参数,与信号对应
        void on_func2(char*, double)(){}		
            // 2个参数
    };
    mySg	sig;
    mySlot	slt;
    sig.sg1.conncent(&slt,&mySlot::on_func1);
    sig.sg2.conncent(&slt,&mySlot::on_func2);
  • disconnection
    解除连接:可以使用disconnect()和disconnect_all()
    sig.sg1.disconnect(&slt);
    sig.sg1.disconnect_all();
  • emiting
    发送信号:可以直接使用()运算符,也可以调用signal的emit函数
    sig.sg1.emit();
    sig.sg2("str",0.1);

实例:

#include <stdio.h>
#include <conio.h>
#include <cstdlib>
#include <iostream>
using namespace std;

#include "sigslot.h"
using namespace sigslot;

#define pause_wait()	{std::cout << "\nPlease press any key to continue.\n";_getch();}


// class
enum	ObjState{Normal = 0, Hidden = 1};
class ObjectBase : public has_slots<> 
{
public:
    ObjectBase(){ px = 0; py = 0; state = Normal; }
    ObjectBase(const int &x, const int &y):px(x), py(y){ state = Normal; }
    ~ObjectBase(){};

    void	onMoveBy(const int &x, const int &y){px += x; py += y;}
    void	onResize(const int &x, const int &y){px = x; py = y;}
    void	onSetState(ObjState s){this->state = s;}
    void	onPrintState()
    {
        if(state == Normal)
            std::cout << "Normal" << std::endl;
        else if(state == Hidden)
            std::cout << "Hidden" << std::endl;
        else
            std::cout << "Error: error state value" << std::endl;
    }

    const int&	getX(){return px;}		
    const int&	getY(){return py;}
    const char* getState()
    {
        if(state == Normal)
            return "Normal";
        else if(state == Hidden)
            return "Hidden";
        else
            return nullptr;
    }

private:
    ObjState	state;
    int		px;
    int		py;
};

class Control
{
public:
    signal2<const int&, const int&>	moveBy;
    signal2<const int&, const int&>	resize;
    signal1<ObjState>	setState;
    signal0<>		printState;;
};

int main(int argc, char* argv[])
{
    ObjectBase obj(10,10);
    Control ctrl;

#if(1)
    ctrl.moveBy.connect(&obj, &ObjectBase::onMoveBy);
    ctrl.resize.connect(&obj, &ObjectBase::onResize);
    ctrl.setState.connect(&obj, &ObjectBase::onSetState);
    ctrl.printState.connect(&obj, &ObjectBase::onPrintState);

    //ctrl.moveBy.disconnect(&obj);
    //ctrl.moveBy.disconnect_all();

    // start pro loop
PRO_Start:
    while(true)
    {
        system("cls");
        cout << "Object Information" << endl;
        cout << "\t Position_x: " << obj.getX() << endl;
        cout << "\t Position_y: " << obj.getY() << endl;
        cout << "\t State: " << obj.getState() << endl;
        cout << "\n";
        cout << "\t m: move object \n"
                "\t r: resize object \n"
                "\t s: set object state \n"
                "\t p: print object state \n"	
                << endl;
        cout << "Input:";

        char ch = getchar();
        switch(ch)
        {
            case 'm':		// move
                ctrl.moveBy(10,10);
                break;
            case 'M':
                ctrl.moveBy.emit(-20,-20);
                break;

            case 'R':
            case 'r':		// resize
                ctrl.resize.emit(0, 0);
                break;

            case 'P':
            case 'p':		// printState
                goto PRO_PrintState;
                break;

            case 's':		// setState
                ctrl.setState(Normal);
                break;
            case 'S':
                ctrl.setState.emit(Hidden);
                break;

            case 'Q':
            case 'q':		// exit
                goto PRO_Exit;
                break;
            default: 
                break;
        }
    }

PRO_PrintState:
    ctrl.printState.emit();
    pause_wait();
    goto PRO_Start;

#endif
    pause_wait();

PRO_Exit:
    return 0;
}


sigc++库

官方地址

http://libsigc.sourceforge.net/

编译

可以在http://download.csdn.net/detail/yehuohan/9600368下载已经编好的库文件,2.8.0版

注意1:
在用高版本编译时,如2.8.0,可能会提示找不到msvc_recommended_pragmas.h,可以在vs的

属性 -> C/C -> 高级 -> 强制包含文件

去掉msvc_recommended_pragmas.h;
或者添加一个msvc_recommended_pragmas.h文件,这里的源代码已经放入了该文件。

注意2:
在使用高版本(如2.9.7)编译时,若提示找不到slot.cc等文件,可以使用低版本中的放入相应位置即可。

在vs中使用

  • 项目 -> VC++目录 -> 包含目录: 添加 sigc++所在的目录
  • 添加下列代码:
        #include <sigc++/sigc++.h>
        #ifdef _DEBUG
            #pragma comment(lib,"sigcd.lib")
        #else
            #pragma comment(lib,"sigc.lib")
        #endif

基本使用:

  • signal
    信号类:可以作为其它类成员,也可直接定义
    //返回值: int,2个参数:char*, double,参数个数可以直接指定
    sigc::signal<int, char*, double>	sg1;
    sigc::signal2<int, char*, double>	sg2;
    class mySg
    {
        sigc::signal2<int, char*, double>	sg3;
    }
  • connection
    连接槽函数,作为类成员时,要继承sigc::trackable;
    ptr_fun, ptr_fun07 : 连接全局函数;
    mem_fun, mem_fun0
    7 : 连接类成员函数;
    ptr_fun,mem_fun与signal之间只要参数类型对应就可连接, 并非一定要数字对应(如:ptr_fun3并非一定要与signal3对应连接)
    sigc::connection ccSg1 = sg1.connect(sigc::ptr_fun(&func1));
    class mySlot: public : sigc::trackable
    {
    public:
        int func2(char*, double)(){}
    } obj;
    sigc::connection ccSg2 = sg2.connect(sigc::mem_fun2(obj,&mySlot::func));
    class mySg:	public : sigc::trackable
    {
        mySg(){auto ccIter_Sg3 = sg3.connect(sigc::mem_fun(*this,&mySg::on_func));}
        sigc::signal2<int, char*, double>	sg3;
        int on_func(char*, double)(){}
    }
  • disconnection
    如果不需要解连接,可以不用定义sigc::connection
    ccSg1.disconnect();
    ccSg2.disconnect();
  • emiting
    sg1.emit("str",0.1);
    sg2.emit("str",0.1);
    // 发送信号:调用signal的emit函数

实例:

#include <stdio.h>
#include <conio.h>
#include <cstdlib>
#include <iostream>
using namespace std;

#include <sigc++/sigc++.h>
#ifdef _DEBUG
    #pragma comment(lib,"sigc280d.lib")
#else
    #pragma comment(lib,"sigc280.lib")
#endif // _DEBUG

#define pause_wait()	{std::cout << "\nPlease press any key to continue.\n";_getch();}


// class
enum	ObjState{Normal = 0, Hidden = 1};
class ObjectBase : public sigc::trackable
{
public:
    ObjectBase(){ px = 0; py = 0; state = Normal; setConnection(); }
    ObjectBase(const int &x, const int &y) :px(x), py(y){ state = Normal; setConnection(); }
    ~ObjectBase(){};

    sigc::signal<void,const char*>	putMsg;

    void	onMoveBy(const int &x, const int &y){px += x; py += y;}
    void	onResize(const int &x, const int &y){px = x; py = y;}
    void	onSetState(ObjState s){this->state = s;}
    void	onPrintState()
    {
        if(state == Normal)
            std::cout << "Normal" << std::endl;
        else if(state == Hidden)
            std::cout << "Hidden" << std::endl;
        else
            std::cout << "Error: error state value" << std::endl;
    }

    const int&	getX(){return px;}		
    const int&	getY(){return py;}
    const char* getState()
    {
        if(state == Normal)
            return "Normal";
        else if(state == Hidden)
            return "Hidden";
        else
            return nullptr;
    }

private:
    ObjState	state;
    int		px;
    int		py;

    void	printMsg(const char* str){std::cout << str << std::endl; }
    void	setConnection()
    {
        putMsg.connect(sigc::mem_fun(*this, &ObjectBase::printMsg));
    }
};

class Control
{
public:
    Control(){}

    sigc::signal<void, const int&, const int&>	moveBy;	
    sigc::signal2<void, const int&, const int&>	resize;		// return void type, and 2 parameters
    sigc::signal<void, ObjState>	setState;

private:
};

// print word steped by space
int printSpaceStr(const char* str)
{
    int				cnt = 0;
    const char*		p = str;
    char			ch;
    std::cout << endl;
    do
    {
        ch = *p;
        cout << ch << ' ';
        cnt++;
    } while (*++p != '\0');
    std::cout << endl;

    return cnt;
}

int main(int argc, char* argv[])
{
    ObjectBase obj(0, 0);
    Control ctrl;

    sigc::signal1<int, const char*>	printSS;
    sigc::connection ccPrintSS = printSS.connect(sigc::ptr_fun1(&printSpaceStr));
    //ccPrintSS.disconnect();

    sigc::signal0<void>		printState;
    printState.connect(sigc::mem_fun(obj, &ObjectBase::onPrintState));

    ctrl.moveBy.connect(sigc::mem_fun(obj, &ObjectBase::onMoveBy));
    ctrl.resize.connect(sigc::mem_fun(obj, &ObjectBase::onResize));
    auto ccIter_SetState = ctrl.setState.connect(sigc::mem_fun(obj, &ObjectBase::onSetState));
    //ccIter_SetState->disconnect();

    // start pro loop
PRO_Start:
    while(true)
    {
        system("cls");
        obj.putMsg.emit("Object Information");
        cout << "\t Position_x: " << obj.getX() << endl;
        cout << "\t Position_y: " << obj.getY() << endl;
        cout << "\t State: " << obj.getState() << endl;
        cout << "\n";
        cout << "\t m: move object \n"
                "\t r: resize object \n"
                "\t s: set object state \n"
                "\t p: print object state \n"	
                "\t a: print space word \n"
                << endl;
        cout << "Input:";

        char ch = getchar();
        switch(ch)
        {
            case 'm':		// move
                ctrl.moveBy.emit(10,10);
                break;
            case 'M':
                ctrl.moveBy.emit(-20,-20);
                break;

            case 'R':
            case 'r':		// resize
                ctrl.resize.emit(0, 0);
                break;

            case 'P':
            case 'p':		// printState
                goto PRO_PrintState;
                break;

            case 's':		// setState
                ctrl.setState.emit(Normal);
                break;
            case 'S':
                ctrl.setState.emit(Hidden);
                break;

            case 'A':
            case 'a':
                goto RPO_PrintSpaceStr;
                break;

            case 'Q':
            case 'q':		// exit
                goto PRO_Exit;
                break;
            default: 
                break;
        }
    }

PRO_PrintState:
    printState.emit();
    pause_wait();
    goto PRO_Start;

RPO_PrintSpaceStr:
    printSS.emit("Sigc_Demo");
    pause_wait();
    goto PRO_Start;

PRO_Exit:
    return 0;
}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 [ yehuohan@gmail.com ]

文章标题:信号槽库:sigslot.h和sigc++使用

本文作者:Y

发布时间:2017-06-09, 18:09:52

最后更新:2020-07-16, 16:37:39

原始链接:http://yehuohan.github.io/2017/06/09/%E6%9D%82%E8%AE%B0/%E4%BF%A1%E5%8F%B7%E6%A7%BD%E5%BA%93%EF%BC%9Asigslot-h%E5%92%8Csigc-%E4%BD%BF%E7%94%A8/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。