首页
社区
课程
招聘
[原创]QT信号槽简易分析_如何查看与分析QT的源码实现
2019-3-19 00:25 7216

[原创]QT信号槽简易分析_如何查看与分析QT的源码实现

2019-3-19 00:25
7216

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

(课堂案例分享, 首次发帖, 若有错误与不足之处, 希望指正)

步骤

  1. 创建demo
  2. 配置环境, 加载静态库
  3. 修改demo, 分析moc文件
  4. 定位关键点, 分析关键函数

使用工具

  1. Visual Studio 2015
  2. QT 5.11.2
  3. 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 环境配置

  1. QT版本配置 (Change QT version)
  2. 安装QT源码, 并在源目录中添加QT源码地址
  3. 在 工具 - 选项 中添加 pdb 文件目录
  4. 测试: F12点进代码中的宏 signals中, 可以得到以下界面, 则表示配置成功!

2.2 Source Insight 环境配置

  1. Source Insight中创建新项目, 将项目名称改为QtSource
  2. 找到QT源码安装目录, 回车, 再加载安装目录中的所有文件
  3. 包含顶层文件和内部文件, 两个都选中
  4. 关闭窗口, 窗口右侧有文件, 则创建项目成功

3 moc文件分析

  • qt_meta_stringdata_CStudent_t : 存储类的字符串相关信息
  • qt_meta_data_CStudent : 存储类中函数相关的信息
    1. 函数名在 qt_meta_stringdata_CStudent_t 中的存储编号
    2. 参数个数
    3. 该函数的具体声明在 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

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

    方法二 : 打开Source Insight, 打开QtSource工程, 在搜索栏中查询QObject.conncet, 得到函数实现的源码
  2. connect函数 : 判断并转化输入的数据, 将数据封装成QT库函数中可以接收的参数, 并调用Connection函数关联信号与槽
    • 实现流程:



  3. Connection函数 : 将信号槽的关联信息以哈希表的形式存储
    • 实现流程

4.3 定位关键点 active

  • 如何定位?
    在槽的实现位置下断点, F5运行至断点后通过下图左下角的栈回溯找到active的实现函数
  • 函数关键点分析
    1. 查找关联链表位置
    2. 调用关联链表中的槽函数

阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!

最后于 2019-3-19 00:27 被埃斯艾克斯编辑 ,原因:
收藏
点赞4
打赏
分享
最新回复 (2)
雪    币: 22980
活跃值: (3347)
能力值: (RANK:648 )
在线值:
发帖
回帖
粉丝
KevinsBobo 8 2019-3-19 10:11
2
0
感谢分享
游客
登录 | 注册 方可回帖
返回