-
-
[原创]QT信号槽简易分析_如何查看与分析QT的源码实现
-
发表于:
2019-3-19 00:25
8034
-
[原创]QT信号槽简易分析_如何查看与分析QT的源码实现
(课堂案例分享, 首次发帖, 若有错误与不足之处, 希望指正)
#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;
};
#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, "")
-
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
: 判断静态/动态调用
- void **_a : 数组指针, 每个指针指向一个函数的地址
- _c : 函数的实现类型
- _id : 函数id, 判断是否实现 & 以何种方式实现该函数
- 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, "")
- 实现流程
- 如何定位?
在槽的实现位置下断点, F5运行至断点后通过下图左下角的栈回溯找到active的实现函数
- 函数关键点分析
- 查找关联链表位置
- 调用关联链表中的槽函数
- 创建demo
- 配置环境, 加载静态库
- 修改demo, 分析moc文件
- 定位关键点, 分析关键函数
- Visual Studio 2015
- QT 5.11.2
- Source Insight
- QT版本配置 (Change QT version)
- 安装QT源码, 并在源目录中添加QT源码地址
- 在 工具 - 选项 中添加 pdb 文件目录
- 测试: F12点进代码中的宏
signals
中, 可以得到以下界面, 则表示配置成功!
- Source Insight中创建新项目, 将项目名称改为QtSource
- 找到QT源码安装目录, 回车, 再加载安装目录中的所有文件
- 包含顶层文件和内部文件, 两个都选中
- 关闭窗口, 窗口右侧有文件, 则创建项目成功
- 函数名在 qt_meta_stringdata_CStudent_t 中的存储编号
- 参数个数
- 该函数的具体声明在 qt_meta_data_CStudent 中的偏移量
- 如何定位?
方法一 : 在VS中进入单步调试模式, 在connect函数上下断点, F11跟进至connect函数中查看函数实现源码
方法二 : 打开Source Insight, 打开QtSource工程, 在搜索栏中查询QObject.conncet, 得到函数实现的源码
- connect函数 : 判断并转化输入的数据, 将数据封装成QT库函数中可以接收的参数, 并调用Connection函数关联信号与槽
- Connection函数 : 将信号槽的关联信息以哈希表的形式存储
- 实现流程
- 查找关联链表位置
- 调用关联链表中的槽函数
创建demo配置环境, 加载静态库修改demo, 分析moc文件定位关键点, 分析关键函数 Visual Studio 2015QT 5.11.2Source InsightQT版本配置 (Change QT version)
安装QT源码, 并在源目录中添加QT源码地址
在 工具 - 选项 中添加 pdb 文件目录
测试: F12点进代码中的宏 signals
中, 可以得到以下界面, 则表示配置成功!
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2019-3-19 00:27
被埃斯艾克斯编辑
,原因: