QT信號槽分析

2021-02-19 雷石安全實驗室


默認安裝好了VS2015 和QT

下載QT pdb和QT src壓縮包(選擇自己的版本,我是5.9.8)

qt下載網址

拷貝自己需要的文件,qt目錄中D:\Qt\Qt5.9.8\5.9.8我是這個

並且把源碼也拷貝進同一目錄,當然其他的目錄也行

設置VS選項

工具->選項->調試->符號

項目->xxxx屬性->vc++目錄(添加源碼路徑)



對著qt的函數或者宏按F12

安裝查看源碼的軟體(Source Insight)

這個工具可以很好的分析源碼



分析moc生成的文件

案例代碼

#include <QObject>class QtClass : public QObject{    Q_OBJECTpublic:    QtClass(QObject *parent);    ~QtClass();    void Test(){        emit Sig1(5);    }signals:    void Sig1(int nVal);                 private slots:    void Slot1(int nVal0){        qDebug() << nVal0;    }}

信號函數只有聲明,沒有實現?

emit Sig1(5);這句代碼調用信號,但是我們沒有實現信號這個函數呀。我們沒有實現,那麼是什麼能夠幫我們實現呢?當然是編譯器。

調試信號函數

F11發現是有實現代碼的吧

打開文件所在目錄

查看moc文件夾,分析編譯器都給我們生成了什麼

定義了一個結構體

qt_meta_stringdata_QtClass_t

struct qt_meta_stringdata_QtClass_t {     QByteArrayData data[6];     char stringdata0[31];};

後面創建了一個結構體靜態變量裡面存放一些類、參數、函數名等信息。這個第一個參數應該是ID,字符串的開始位置,字符串size

QT_MOC_LITERAL(0, 0, 7), // "QtClass"
static const qt_meta_stringdata_QtClass_t qt_meta_stringdata_QtClass = {     {QT_MOC_LITERAL(0, 0, 7), QT_MOC_LITERAL(1, 8, 4), QT_MOC_LITERAL(2, 13, 0), QT_MOC_LITERAL(3, 14, 4), QT_MOC_LITERAL(4, 19, 5), QT_MOC_LITERAL(5, 25, 5)     },    "QtClass\0Sig1\0\0nVal\0Slot1\0nVal0"};

qt_meta_data_QtClass : 存儲類中函數相關的信息

static const uint qt_meta_data_QtClass[] = {         7,              0,              2,   14,        0,    0,        0,    0,        0,    0,        0,              1,               1,    1,   24,    2, 0x06 ,        4,    1,   27,    2, 0x08 ,24     QMetaType::Void, QMetaType::Int,    3,27     QMetaType::Void, QMetaType::Int,    5,       0        };

qt_static_metacall類的信號/槽函數調用的實現地址判斷傳進來的ID然後調用函數

void QtClass::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, {    if (_c == QMetaObject::InvokeMetaMethod) {        QtClass *_t = static_cast<QtClass *>(_o);         Q_UNUSED(_t)         switch (_id) {        case 0: _t->Sig1((*reinterpret_cast< int(*)>(_a[1]))); break;         case 1: _t->Slot1((*reinterpret_cast< int(*)>(_a[1]))); break;         default: ;        }    } else if (_c == QMetaObject::IndexOfMethod) {         int *result = reinterpret_cast<int *>(_a[0]);        {            typedef void (QtClass::*_t)(int );             if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&QtClass::                *result = 0;                 return;            }        }    }}


staticMetaObject : 類信息的總和

紅色框是父類地址,藍色是存儲字符串的結構體的地址,黑色是存放信號槽函數信息的結構體,類的信號/槽函數調用的實現地址

metaObject:判斷靜態/動態調用

qt_metacast:返回類名稱

+qt_metacall:函數調用

void** _a:數組指針, 每個指針指向一個函數的地址

_c:實現函數的類型

_id : 函數id, 判斷是否實現 & 以何種方式實現該函數

信號函數的實現

void* _a[]是一個信號對應的槽函數的地址

一個信號可以對應多個槽,所有這裡是void* _a[]數組

Q_OBJECT

從這裡看是不是很明顯的能看出,這裡寫了虛函數,然後生成moc文件幫我們實現

* qmake ignore 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 *, Q     QT_WARNING_POP \    struct QPrivateSignal {}; \    QT_ANNOTATE_CLASS(qt_qobject, "")



檢查函數

判斷參數是否為NULL

給Sender賦值獲取名字、對象、參數等

獲取sender的Index,並且判斷是否有效

接收方信息

判斷信號槽是否被關聯

判斷接收方是否有效可以被關聯

檢查發送者和接收者參數是否一致

執行關聯操作函數

進入實現函數

先是強轉了sender 和receiver保存在兩變量裡面

檢測版本

估計是為了防止多線程,給了鎖

生成信號槽的對應關係Connection,並把Connection插入ConnectionList中

為對應的connect賦值

解鎖,並且檢查是否關聯成功







當我們發Sig1信號時調用的函數

紅框計算父類的信號

前面做了一系列檢查,是否還關聯著

構造一個ConnectListRef的結構體,類似ConnectList引用

這裡用上面的Index找到關聯鍊表

遍歷表找到對應得connect

調用鍊表得槽函數









相關焦點

  • Qt實現 結合opencv播放視頻
    2、效果圖本項目實現了通過opencv+qt播放視頻的功能。其中用qt製作前端,opencv負責處理視頻的解碼過程。().height())); cv::cvtColor(matDes, matDes, COLOR_BGR2RGB); int matDesSize = matDes.cols*matDes.rows*matDes.elemSize(); memcpy(_image.bits(), matDes.data, matDesSize); update();}mat對象通過信號槽傳遞而來
  • 學習qt 01gui對比
    語言框架c++Qt,wxWidgets,Htmlayout,...c#WinForm、WPFaardioaardioqt優點:簡單易學,資料豐富
  • Qt5軟體開發-第1章 QT入門(上)
    1.3 QT下載Qt Creator官網下載地址:https://www.qt.io/download/QT所有版本下載地址:http://download.qt.io/archive/qt/Qt Creator是跨平臺的 Qt IDE, Qt Creator 是 Qt 被 Nokia 收購後推出的一款新的輕量級集成開發環境
  • Qt 組件布局
    然後進行信號槽的連結。這點後面再詳細說明。然後是一個QHBoxLayout,就是一個水平布局,按照從左到右的順序進行添加,使用 addWidget 添加好組件後,調用 QWidget 的 setLayout 把 QWidget 的 layout 設置為我們定義的這個 Layout,這樣,程序就完成了!雖然我並沒有添加任何代碼,但是那個 layout 就已經明白該怎樣進行布局。
  • Qt 串口上位機開發《Rice 上位機 學習開發》
    ①  頭文件(mainwindow.h)內容:通過Win_QextSerialPort定義串口對象myCom,定義一個串口是否打開標誌,然後定義讀數據信號槽函數readMyCom(),打開or關閉串口按鍵信號槽函數openOrCloseBtn
  • Qt線程的基本概念
    也就是你可以通過信號槽來進行線程之間的通信(這樣就不需要寫各種回調函數了)。這大大的簡便了線程通信的複雜邏輯。自己線程發的信號槽如果不注意的話,線程的槽函數也不會響應的。(當然有很多方法能做到這件事兒,但是不推薦)下面介紹新的寫法,重寫QObject,move到新的線程中。
  • Qt-Thread線程官方的推薦的寫法
    今天給大家介紹新的實現方式,這種實現方式相當靈活,可以任意的啟動,暫停之類的操作,都是通過Qt的信號槽來實現。我們先繼續實現上一個例子。這次使用新的實現方式。重寫QObject,move到新的線程中。這樣是QObject自己的消息循環放到了新的線程中,跨線程之間信號槽就隨隨便便的使用了。
  • 聊聊C、C++、Boost、Qt與嵌入式開發
    Qt裡封裝了好多C++的類庫,各種功能都有,比如常用的字符串處理類QString,可變長數組(字節數組)QByteArray,聯合類型QVariant,以及類似於標準庫的容器模板類QMap、QVector、QList等等,當然Qt還有一個比較出色的地方,就是信號槽框架,這個信號槽用於類之間的通信。
  • Qt 學習之路 2:QML 語法
    博客地址:https://www.devbean.net/2013/12/qt-study-road-2-qml-syntax/正文前面我們已經見識過 QML 文檔。一個 QML 文檔分為 import 和對象聲明兩部分。如果你要使用 Qt Quick,就需要 import QtQuick 2。QML 是一種聲明語言,用於描述程序界面。
  • Qt的線程的控制-開始,暫停,停止,繼續,銷毀
    >}void WorkThread::Continue(){    m_bPause = false;}void WorkThread::Destory(){    m_bDestory = true;}上面的代碼為控制線程的函數,下面是UI線程通過信號槽來控制代碼
  • 【Qt開發】第一個Qt程序Hello World!
    一:說在前頭我的第一份工作是做生產工具,當時用的MFC,IDE是VC6.0,現在想想真是古董級別,10年至今,微軟也一直沒有對MFC進行升級,冥冥中感覺微軟自己都放棄MFC了,市場上貌似MFC的崗位越來越少了,基本上也都是原先的項目維護,qt
  • 選擇QT作為Windows客戶端開發框架
    QT強大的信號槽機制QT信號槽機制本質是一種回調的實現,A對象定義信號、觸發信號,B對象定義槽,連接信號,當A對象觸發信號時,B對象的槽就會被調用。同一個信號可以連接多個槽,實現一對多的調用。
  • Qt實用技能4-認清信號槽的本質
    分析:這裡是以」mouse」這個字符串作為連接tom和jerry的關鍵。這只是一種簡單、粗糙的示例實現。觀察者模式在GOF四人幫的書籍《設計模式》中,有一種觀察者模式,可以比較優雅地實現同樣的功能。
  • Qt開發1200例—例0001 Qt的下載
    例0001 Qt的下載相當一部分朋友下載Qt的時候會選擇去https://www.qt.io/這個地址下載,但是因為官網對中文支持並不是很好,所以導致一些英文基礎薄弱的朋友下載時候比較吃力,再加上Qt有商業版和開源版的區別,就更加有些迷茫了。
  • 收集一些Qt學習網站
    Qt 官網https://www.qt.io了解Qt最新資訊開發動態的窗口。Qt 資源下載http://download.qt.io最新Qt安裝程序可以在這裡找到。Qt 博客者聚集地http://planet.qt.io很多Qt大神都在裡面。
  • Qt 5.15 LTS發布,Qt 6要來了
    Qt 3D 獲得了更好的性能分析和調試支持以及一些較小的新功能。 Qt Multimedia 現在支持渲染到多個表面。Qt GUI 中,圖像縮放和轉換例程現在在許多用例中都是多線程的。 Qt Network 現在支持 TLS 1.3 session tickets 和可配置的 timeouts。
  • 使用CMake部署Qt應用程式
    查找windeployqtfind_package(Qt5 COMPONENTS Core CONFIG)#加載Qt5::Core對應的庫配置文件,能夠找到Qt的bin目錄if(NOT _qt5_install_prefix) return()endif()## message(STATUS
  • VS2019:基於Qt+OpenCV創建項目
    環境:win10,VS 2019,qt 5.12.5,opencv 4.1.0二、具體配置流程VS創建Qt項目插件安裝需要VS 不自帶創建Qt項目,所以這裡需要給 VS裝一個插件,叫做qt-vsaddin-msvc2019-2.4.1.vsix,根據自己的vs版本,可以從這裡下載,下載完成之後,雙擊,按照提示就可以安裝完畢。
  • Qt值得學習嗎?詳解Qt的幾種開發方式
    qt值得學習嗎?嵌入式要學的東西真的很多,我們可能會說不寫界面的話就不用學qt了?我不贊同。Qt的實現主要是採用p-impl手法,實現接口與實現分離,它有很好的消息循環機制,有的對象與線程的相關性,它也有藉助moc生成反射元信息,這種設計方法至今仍然非常適用。qt內核部分其實是完全和界面無關的,你完全可以拋開Qt GUI部分來學習和使用Qt。