欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-09 21:33:33
用qt的知道,qt有方便简单的信号槽机制,但需要专门的qt工具处理。 如果想直接使信号槽就可以使用sigslot库,或者sigc++库,或者boost中的signals,这里介绍sigslot和si...

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

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


sigslot库

官方地址

在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    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 
#include 
#include 
#include 
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 moveby;
    signal2 resize;
    signal1   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++库

官方地址

编译

下载已经编好的库文件,2.8.0版
注意1:在用高版本编译时,如2.8.0,可能会提示找不到ms_recommended_pragmas.h,可以在vs的

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

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

在vs中使用

* 项目 -> vc++目录 -> 包含目录: 添加 sigc++所在的目录
* 添加下列代码:
        #include 
        #ifdef _debug
            #pragma comment(lib,"sigcd.lib")
        #else
            #pragma comment(lib,"sigc.lib")
        #endif

基本使用:

signal
信号类:可以作为其它类成员,也可直接定义
    //返回值: int,2个参数:char*, double,参数个数可以直接指定
    sigc::signal    sg1;
    sigc::signal2   sg2;
    class mysg
    {
        sigc::signal2   sg3;
    }
connection
连接槽函数,作为类成员时,要继承sigc::trackable;
ptr_fun, ptr_fun0~7 : 连接全局函数;
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   sg3;
        int on_func(char*, double)(){}
    }
disconnection
如果不需要解连接,可以不用定义sigc::connection
    ccsg1.disconnect();
    ccsg2.disconnect();
emiting
// 发送信号:调用signal的emit函数
    sg1.emit("str",0.1);
    sg2.emit("str",0.1);

实例:

#include 
#include 
#include 
#include 
using namespace std;

#include 
#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  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  moveby; 
    sigc::signal2 resize;     // return void type, and 2 parameters
    sigc::signal    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 printss;
    sigc::connection ccprintss = printss.connect(sigc::ptr_fun1(&printspacestr));
    //ccprintss.disconnect();

    sigc::signal0     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;
}