深入理解QT的SIGNAL\SLOT机制(五):信号的发射过程

来源:互联网 发布:mac装什么虚拟机 编辑:程序博客网 时间:2024/06/05 11:19

我们来看信号的发起过程,先来看一个宏定义:# define emit,这个宏定义将emit定义为空,也就是说你在emit mysignal()的时候,这行代码其实就是mysignal(),所以信号就是函数,只是换了个概念而已!
废话不多说,来DEBUG:
这里写图片描述
我们在11行打断点F11进入:

// SIGNAL 0void MyWidget::mysignal(){    QMetaObject::activate(this, &staticMetaObject, 0, nullptr);}

居然直接调用了moc文件中的mysignal函数,现在是不是更清楚信号就是函数了啊?这里的this是MyWidget对象,staticMetaObject就是第二章提到的静态QMEtaObject,其余都是空。进入active函数之前回去先计算偏移量:
这里写图片描述
822~824行:将QMetaObject的所有父类偏移量加起来,目的是找到子类的第一个信号的偏移量(5.9.1中除了类名信息之外,只存储了信号和槽的信息)。现在进入active函数:
这里写图片描述
3636行:子类第一个信号的偏移量+当前偏移量,就是我们需要的mysignal信号的偏移量。
3637~3660行:进行安全检查,检查是否绑定信号和槽。
接着来看:
这里写图片描述
3694行:根据信号的signal_index下标查找到connectionList,这个connectionList存储的是所有绑定到该信号的槽函数信息;
这里写图片描述
3700~3705行:拿到列表的first和last,进行遍历。
3707~3709行:receiver是空,就意味着没有槽函数,continue;
3712~3721行:针对不同类型进行不同的处理;
我们的是在统一个线程中,调用3743行的switchSender函数,不同线程的是放到队列中去;
这里写图片描述
来看switchSender函数:

 inline void switchSender(QObject *receiver, QObject *sender, int signal_absolute_id)    {        this->receiver = receiver;        currentSender.sender = sender;        currentSender.signal = signal_absolute_id;        currentSender.ref = 1;        previousSender = QObjectPrivate::setCurrentSender(receiver, &currentSender);        switched = true;    }

发现该函数基本是进行值拷贝,继续来看active函数:
3757~3766行:如果c->callFunction不为空,并且c->methodOffset在QMetaObject的methodOffset之内(保证调用的函数偏移量不超过QMetaObject的偏移量),就可以调用callFunction.
我们看到const auto callFunction = c->callFunction;
callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv ? argv : empty_argv);
实际上就是在调用callFunction,也就是moc_test.cpp中的qt_static_metacall函数。
调用完之后继续执行do{}while(),知道所有的槽被调用。

接下来按F11,进入callFunction
这里写图片描述
可以看到确实调用了moc_test.cpp中的static_metacall函数,
71行:格局传入的id调用对应的槽函数,所以myslot被调用。
OK,完结撒花!
如有问题欢迎指正


电子科技大学
胡力卫
15373632531@163.com

原创粉丝点击