解析 Qt 在 Windows 下入口函數實現實例
Qt 在 Windows 下入口函數實現實例是本文介紹的內容。Windows下入口函數 有 main 和 WinMain 兩種(還有其對應的 Unicode 版本,此處不考慮)。一般來說,前者是 控制臺程序 的入口函數,后者是 GUI 程序的入口函數。
Qt下只有 main?
Qt 是C++ 的庫,它也改變不了 main 和 WinMain 兩種入口函數的事實;但實際中,我們在 Qt 程序中只寫main函數,而從不寫WinMain函數。這是怎么回事呢?
WinMain
當我們將 Windows 版的Qt裝好以后,在其lib目錄內,會發現兩個庫:qtmain.lib 和 qtmaind.lib(或者 libqtmain.a和 libqtmaind.a)
很容易判斷,這兩個庫是同一個東西(帶d的是debug版,不帶的是release版),所以我們下面可以稱其為一個庫。那么這一個庫有什么用呢?
如果細心的話,我們會發現:當我們的pro文件內 不指定 CONFIG += console (而且也不使用 qtestlib模塊)時,程序編譯時會鏈接該庫。最終的程序執行時也不會出現控制臺。
如果我們指定了 CONFIG+= console (或者使用了 qtestlib模塊)時,程序鏈接時將不需要該庫,程序運行時也會出現控制臺。
那么?這個 qtmain 庫內到底是什么東西呢,會不會和WinMain有什么瓜葛?
如果找到源碼就好辦了,恩 %QTDIR%\src\winmain\qtmain_win.cpp
打開一看,一切明白了:
- /*
- WinMain() - Initializes Windows and calls user's startup function main().
- NOTE: WinMain() won't be called if the application was linked as a "console" application.
- */
- #ifdef Q_OS_WINCEint WINAPI WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR
- /*wCmdParam*/,
- int cmdShow)#elseextern "C"int APIENTRY WinMain(HINSTANCE instance,
- HINSTANCE prevInstance, LPSTR
- /*cmdParamarg*/, int cmdShow)#endif{...}
原來WinMain在這兒藏著呢。當我們創建不帶控制臺的程序時,Qt將鏈接qtmain這么庫,這個庫封裝了WinMain。最終我們自己的main函數在這個WinMain中被調用了。
這么做的好處? 我想最主要的一點或許是:
把各種平臺下的入口函數封裝起來,易于編譯跨平臺的程序(至少不用我們用預處理宏來寫各種入口函數了)
入口函數與嵌入可執行文件的啟動函數
main
- mainCRTStartup
- inMain
- WinMainCRTStartup
MSVC
對 MSVC 系列的編譯器,指定鏈接子系統比如 /subsystem:console,鏈接器就會尋找main函數,并選擇mainCRTStartup函數;對windows子系統,情況類似。
當我們程序的入口函數是 WinMain 時,如果指定 console 子系統,鏈接器將報錯,這時我們可以指定入口點啟動函數 /entry:WinMainCRTStartup 來解決這種問題。
Mingw
Mingw 的情況與 MSVC系列有所不同,據說是下面這個樣子:
Mingw運行時提供了兩個入口點啟動函數:
mainCRTStartup() 對控制臺程序 (-subsystem,console)
WinMainCRTStartup() 對GUI程序 (-subsystem,windows)
但這兩個函數都調用的是:
__mingw_CRTStartup()這樣一來,控制臺程序和GUI程序的行為時一樣的:
調用 main 函數
如果 main 函數不存在,libmaingw32.a將被鏈接進來,該庫里面提供了一個main函數(該函數將調用用戶的WinMain函數)
小結:解析 Qt 在 Windows 下入口函數實現實例的內容介紹完了,希望本文對你有所幫助。