詳細分析Qt中moc檔案

2021-09-01 17:30:11 字數 4603 閱讀 7601

詳細分析qt中moc檔案

一直想寫一片詳細分析qt中moc檔案的文章,今天終於是完成了。迫不及待的分享給大家,希望大家可以賞個臉,認真的看完,希望對大家的學習也有幫助。請看下面的分析qt中moc檔案的詳細內容。

qt 不是使用「標準的」c++語言編寫,而是對其進行了一定程度的擴充套件。我們可以從qt增加的關鍵字看出來:signals、slots或emit。但是使用gcc編譯時,編譯器並不認識這些非標準c++的關鍵字,那麼就需要qt自己將擴充套件的關鍵字處理成標準的c++**。qt在編譯之前會分析原始檔,當發現包含了 q_object 巨集,則會生成另外乙個標準的c++原始檔,這個原始檔中包含了 q_object 巨集的實現**,這個原始檔名字是將原檔名前面加上 moc_ 構成,這個新的檔案同樣將進入編譯系統,最終被鏈結到二進位制**中去,此時,qt將自己增加的擴充套件轉換成了標準的c++檔案,moc 全稱是 meta-object compiler,也就是「元物件編譯器」。這就是moc檔案的由來。

下面我們來分析一下moc檔案:

一 示例**如下:

#include

class ctestmoc : public qobject

~ctestmoc(){}

signals:

void test1();

void test2(int itemp);

private slots:

void ontest1();

void ontest2(int itemp);

};二 q_object巨集

#define q_object

public:

q_object_check

static const qmetaobject staticmetaobject;

virtual const qmetaobject *metaobject() const;

virtual void *qt_metacast(const char *);

qt_tr_functions

virtual int qt_metacall(qmetaobject::call, int, void **);

private:

q_decl_hidden_static_metacall static void qt_static_metacall(qobject *, qmetaobject::call, int, void **);

struct qprivatesignal {};

此巨集在qobjectdefs.h標頭檔案中定義

1 q_object_check 定義如下:

#define q_object_check

template inline void qt_check_for_qobject_macro(const thisobject &_q_argument) const

巨集展開最終會呼叫qyouforgottheq_object_macro這個內聯函式。這個函式始終返回0,但是很不明白,為什麼之後還要新增一句 i=i?,刨根之後,發現q_object_check巨集並沒有做什麼工作。

inline int qyouforgottheq_object_macro(t, t)

2 static const qmetaobject staticmetaobject 靜態的元物件,這個物件在moc檔案裡會構建,在那裡就能看到整個訊號&槽的全貌。

3 virtual const qmetaobject *metaobject() const; 返回乙個元物件。

4 virtual void *qt_metacast(const char *); 元物件中的字元資料轉換。

5 virtual int qt_metacall(qmetaobject::call, int, void **); 元物件呼叫入口,注意此函式是public的,槽函式呼叫也是由這個函式開始。

6 static void qt_static_metacall(qobject *, qmetaobject::call, int, void **); 由qt_metacall函式呼叫,槽函式呼叫真正處理函式。q_decl_hidden_static_metacall這個巨集看到最後和linux系統有關,其它系統這個巨集是乙個空的巨集。

三 moc檔案分析

先說結論在這裡。

1 qt的訊號&槽之間的呼叫不是通過指標方式呼叫的而是通過索引方式來呼叫的.

2 訊號也是乙個函式。

moc檔案有幾個重要資料結構,把這幾個結構之間關係講清楚大家就清楚qt的訊號槽機制是如何工作的了。

第乙個結構是 qt_meta_stringdata_ctestmoc_t 定義如下:

struct qt_meta_stringdata_ctestmoc_t ;

data欄位是乙個由byte陣列組成的陣列,陣列大小根據訊號&槽個數有關,這個陣列在呼叫qobject的connect函式時用來匹配訊號名或槽名。

stringdata 存放的是字元資源,存放全部的訊號名、槽名、類名。

static const qt_meta_stringdata_ctestmoc_t qt_meta_stringdata_ctestmoc = ,

「ctestmoc\0test1\0\0test2\0itemp\0ontest1\0」

「ontest2\0」

};qt_meta_stringdata_ctestmoc 這個就是乙個 qt_meta_stringdata_ctestmoc_t結構體的例項。

qt_moc_literal(0, 0, 8), 這個巨集生成乙個byte陣列,第一引數是索引,大家可以看到索引是由 0 - 6 共7個組成,對應的是data欄位的長度7,第二個引數是在stringdata欄位中的開始位置,第三個引數是長度。

例如 qt_moc_literal(0, 0, 8) 索引是0, 開始位置是0, 長度是8,對應的字元是"ctestmoc",後面的以此類推。

第二個結構是 static const uint qt_meta_data_ctestmoc

這個結構體描述的是訊號&槽在呼叫時的索引、引數、返回值等資訊。

static const uint qt_meta_data_ctestmoc = ;

這個陣列的前14個uint 描述的是元物件的私有資訊,定義在qmetaobject_p.h檔案的qmetaobjectprivate結構體當中,qmetaobjectprivate結構體我們不做深入分析,但是,在這個結構體中4, 14, // methods這個資訊描述的是訊號&槽的個數和在表中的偏移量,即14個uint之後是資訊&槽的資訊

qt_meta_data_ctestmoc這個表中我們可以看到每描述乙個訊號或槽需要5個uint

例如,從表的第14個uint開始描述的訊號資訊

// signals: name, argc, parameters, tag, flags

1, 0, 34, 2, 0x06,

3, 1, 35, 2, 0x06,

name:對應的是qt_meta_stringdata_ctestmoc 索引,例如1 對應的是test1

argc:引數個數

parameters : 引數的在qt_meta_data_ctestmoc這個表中的索引位置。

例如 // signals: parameters

qmetatype::void,

qmetatype::void, qmetatype::int, 4,

void 是訊號的返回值,qmetatype::int是引數型別, 4 是引數名,在qt_meta_stringdata_ctestmoc中的索引值。

tag:這個欄位的數值對應的是qt_meta_stringdata_ctestmoc 索引,在這個moc檔案裡對應的是乙個空字串,具體怎麼用,在源**裡沒看懂。

flags:是乙個特徵值,是在 enum methodflags 列舉中定義。

enum methodflags ;

大家可以看到,槽對應的是methodslot 0x08, 訊號對應的是methodsignal 和accesspublic 相或。

第三部分 qobject 中靜態函式 qt_static_metacall 實現

void ctestmoc::qt_static_metacall(qobject *_o, qmetaobject::call _c, int _id, void **_a)…}

現在看這個就比較直觀了,qt_metacall方法通過索引呼叫其它內部方法。qt動態機制不採用指標,而由索引實現。實際呼叫方法的工作由編譯器實現。這使得訊號和槽的機制執行效率比較高。

引數由乙個指向指標陣列的指標進行傳遞,並在呼叫方法時進行適當的轉換。當然,使用指標是將不同型別的引數放在乙個陣列的唯一辦法。引數索引從1開始,因為0號代表函式返回值。

第四部分 qobject 中靜態staticmetaobject的賦值

const qmetaobject ctestmoc::staticmetaobject =

};ok,通過這個靜態變數就儲存了moc檔案的訊號&槽的呼叫索引資訊。在訊號&槽繫結的時候就是通過這些資訊一步一步建立的繫結關係。

第四部分 訊號就是函式。

大家可以moc檔案中看到訊號的實現。

以上就是詳細分析qt中moc檔案的內容,不知道大家是否堅持看完了,相信看完後對你很有幫助。更多參考資料可以在華清遠見的官網進行檢視,華清遠見提供免費的教程,供大家學習!

const詳細分析

最近在分析 linux 驅動的過程過程中遇到一些關於 const 的使用,現在在這裡詳細剖析一下 一,const int p 首先分析一下幾個概念 1 p 是乙個指標變數,因而它也是乙個變數,所謂變數就有變數的位址和變數的值,而這裡 p變數的值就是乙個位址,該位址下存放的是乙個整數,p的值等於這個整...

約數詳細分析

約數詳細分析 我們先來認識一下約數 約數分正約數和負約數兩種,我們一般只討論正約數。也就是說,接下來所提的約數,只考慮正約數。如果有乙個數k,滿足k n,那麼k就是n 的約數 因數 n是k的倍數。求乙個數的約數是資訊學競賽裡乙個基礎的不能再基礎的問題。如果只求乙個數,最容易想到的就是列舉。當然列舉也...

vue cli 詳細分析

vue lic 是 vue 官方提供的腳手架工具,預設搭建好乙個專案的基本架子,我們只需要在此基礎上進行相應的修改即可。注意 安裝 vue cli 前需要事先配置好 node 環境 npm install g vue cli 如果是 mac 電 sudo表示以管理員的許可權 sudo install...