Qt開發中,可以在.pro文件中設置一些宏定義的值,來改變工程的編譯配置。如下圖所示,一個最基本的工程中.pro文件中,會有QT
、CONFIG
、SOURCE
、TARGET
等宏定義的設置,其中QT
指定工程用的qt的功能模塊,SOURCE
指定工程源文件,TARGET
指定生成的目標文件,有的工程還會添加HEADERS
與LIBS
的宏定義,用於指定工程編譯所需的頭文件核動態庫文件的路徑與名稱。
那麼在c++代碼是否可以獲取到這些宏定義呢?
在一個QT工程代碼中,可以非常方便的用"QCoreApplication::applicationDirPath()"程序來獲取可執行文件的路徑,但是如果c++程序中想獲取工程源代碼的路徑(非可執行文件路徑)的話,就有些難度了,因爲並沒有相應的API函數,並且編譯後生成的可執行文件與源碼目錄並沒有關係。
在QT工程的.pro文件則可以很輕易做到這點,用$${PWD}
就指向了當前.pro文件的路徑,一般也就是工程源碼路徑。接下來就以在c++程序中獲取工程源碼路徑爲例,講一下如何在c++程序中引用.pro文件中的宏定義。
1. DEFINES宏
Qt工程中可以通過在.pro文件中添加DEFINES
宏來實現全局宏定義,用法一般有兩種:
DEFINES += MACRO_NAME
或者
DEFINES += MACRO_NAME=VALUE
DEFINES
宏定義的內容會以"-D$DEFINES"的形式添加到編譯器的編譯參數中,而-D選項是用來在編譯的時候定義宏的。比如:
gcc -DDEBUG // -D後面直接跟宏名稱,相當於定義了這個宏,默認這個宏內容爲1
gcc -DNAME=VALUE // -D後面跟key=value表示定義key這個宏,它的內容是value
爲了有個直觀的認識,下面以一個簡單的宏爲例,我們在.pro文件中添加一條DEFINES
宏定義,然後編譯這個工程。
從圖中可以看出,在.pro文件中添加"DEFINES += PI_MY=3.1415926"宏定義後,編譯.cpp源碼文件時,編譯器自動添加了"-DPI_MY=3.1415926"的參數,這個PI_MY
就是我們添加的宏,這個宏可以在c++源碼中使用,我們在main.cpp中打印PI_MY
的值,程序運行如下。
2. 宏轉字符串處理
如上一節,數字類型的宏比較好處理,在c++程序中直接引用即可,但是字符串形式的宏就比較麻煩了,因爲編譯器-D參數只能傳遞宏定義的原始文本,沒法給它添加雙引號的符號,在程序文本中宏預處理後的字符串,由於不帶"的符號,在編譯時不能被正確識別成字符串,就會引發編譯錯誤。
比如我們在在.pro文件中添加"DEFINES += MPATH=/home/my"宏定義後,通過編譯器傳遞給c源碼中MPATH
宏的值是/home/my,而不是"/home/my",這樣在c程序中是無法直接引用的。
好在c語言定義中,可以#符號把宏參數變成一個字符串,如下圖所示。
在圖中,TEST_ABC
是一個宏定義,在它作爲參數傳遞給STR宏後,就被轉成了字符串,這樣只能轉換宏名爲字符串,如果想轉換宏定義的值爲字符串的話,可以用如下方式進行。
在圖中,我們取消了cout << TEST_ABC << endl
代碼,因爲TEST_ABC
宏的值是一串原始文本,這樣寫會編譯報錯,所以通過宏參數傳遞後,最後用#符號將宏的值轉成字符串才能正常用cout打印出來。
3. 獲取工程源碼路徑
接下來回到Qt Creator工程,我們定義一個SRC_PATH
宏,指定爲源碼路徑,然後在c程序中打印出來該路徑。首先看.pro文件寫法。
可以看出"SRC_PATH=${PWD}“被編譯器用”-DSRC_PATH=F:/qt-workspace/MacroTest"的形式傳遞,接下來看c程序中如果獲取自定義的宏SRC_PATH
。代碼及運行結果如下圖所示。
可以看出,在c++程序中,順利獲取到了.pro文件中的宏定義變量。