查看原文
其他

信号/槽原理分析 | 如何查看与分析QT的源码实现

埃斯艾克斯 看雪学院 2019-05-25



步骤


1、创建demo

2、配置环境, 加载静态库

3、修改demo, 分析moc文件

4、定位关键点, 分析关键函数



使用工具


Visual Studio 2015

QT 5.11.2

Source Insight



实操


1、创建demo


#include <QObject>

class CStudent : public QObject
{
Q_OBJECT

public:
CStudent(QObject *parent);
~CStudent();

void SetAge(int nAge) {
emit age(3, nAge);
}

signals:
void age(int n, double nAge);

public slots:
void OnAgedChange(int n, double nAge) {
m_nAge = nAge;
}

private:
int m_nAge;
};


2.1、 Visual Studio 环境配置


① QT版本配置 (Change QT version)



② 安装QT源码, 并在源目录中添加QT源码地址



③ 在 工具 - 选项 中添加 pdb 文件目录



④ 测试:

F12点进代码中的宏 signals中,可以得到以下界面,则表示配置成功!



2.2 Source Insight 环境配置


① Source Insight中创建新项目,将项目名称改为QtSource:



② 找到QT源码安装目录,回车,再加载安装目录中的所有文件



③ 包含顶层文件和内部文件,两个都选中



④ 关闭窗口,窗口右侧有文件,则创建项目成功。


3、moc文件分析


① qt_meta_stringdata_CStudent_t :存储类的字符串相关信息



② qt_meta_data_CStudent : 存储类中函数相关的信息


  • 函数名在 qt_meta_stringdata_CStudent_t 中的存储编号

  • 参数个数

  • 该函数的具体声明在 qt_meta_data_CStudent 中的偏移量



③ staticMetaObject:类信息的总和。
 


④ qt_metacast : 返回类名称。



⑤ qt_metacall : 函数调用


  • void **_a : 数组指针, 每个指针指向一个函数的地址

  •  _c : 函数的实现类型

  • _id : 函数id, 判断是否实现 & 以何种方式实现该函数


⑥ void CStudent::age(int _t1, double _t2) : 信号的实现



⑦ metaObject : 判断静态/动态调用



4.1 定位关键点 QObject


① Q_OBJECT 宏


#define Q_OBJECT \
public: \
QT_WARNING_PUSH \
Q_OBJECT_NO_OVERRIDE_WARNING \

static const QMetaObject staticMetaObject; \
virtual const QMetaObject *metaObject() const; \
virtual void *qt_metacast(const char *); \
virtual int qt_metacall(QMetaObject::Call, int, void **); \
QT_TR_FUNCTIONS \
private: \
Q_OBJECT_NO_ATTRIBUTES_WARNING \
Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
QT_WARNING_POP \
struct QPrivateSignal {}; \
QT_ANNOTATE_CLASS(qt_qobject, "")


‍‍4.2  定位关键点 connection


① 如何定位?


方法一 : 在VS中进入单步调试模式,在connect函数上下断点,F11跟进至connect函数中查看函数实现源码



方法二:打开Source Insight,打开QtSource工程,在搜索栏中查询QObject.conncet,得到函数实现的源码



②connect函数:判断并转化输入的数据,将数据封装成QT库函数中可以接收的参数,并调用Connection函数关联信号与槽。


实现流程:






③ Connection函数 : 将信号槽的关联信息以哈希表的形式存储


实现流程:



4.3 定位关键点 active


① 如何定位?


在槽的实现位置下断点,F5运行至断点后通过下图左下角的栈回溯找到active的实现函数



② 函数关键点分析


Ⅰ 查找关联链表位置



Ⅱ 调用关联链表中的槽函数





- End -




看雪ID:埃斯艾克斯         

https://bbs.pediy.com/user-833985.htm


本文由看雪论坛 埃斯艾克斯 原创

转载请注明来自看雪社区



热门图书推荐

立即购买!





热门文章阅读

1、API监控+代码乱序的壳

2、二进制加壳原理与实现

3、Linux内核fuzz技术——trinity




公众号ID:ikanxue

官方微博:看雪安全

商务合作:wsc@kanxue.com



↙点击下方“阅读原文”,查看更多干货!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存