從前面幾篇,我們已經得到一些結論。
程序是可以自定義入口的,但是如果在入口中使用了一些CRT相關的函數,而沒有正確的進行初始化工作的話,即使編譯不出問題,在運行時也會出現內存錯誤等問題的。
那我們可以寫出完全不用到CRT庫的程序嗎?當然可以,既然CRT庫也是微軟寫的,甚至我們可以用另外一個CRT庫來代替它。不過這個算是另外一個話題了。先看看不使用CRT庫的hello world是啥樣的吧。
不使用C運行時庫的測試代碼
view sourceprint?01 #include <windows.h>
02
03 DWORD StringLen(const char * str)
04 {
05 const char *eos = str;
06 while( *eos++ ) ;
07 return( (DWORD)(eos - str - 1) );
08 }
09
10 void WriteString(const char * str)
11 {
12 HANDLE hOut;
13 DWORD Length;
14 DWORD result;
15 hOut=GetStdHandle(STD_OUTPUT_HANDLE);
16 Length=StringLen(str);
17 WriteFile(hOut,str,Length,&result,0);
18 }
19
20 int myentry(void)
21 {
22 WriteString("Hello World!");
23 ExitProcess(0);
24 return 0;
25 }
編譯:
cl /c /Zl myentrytest.c
鏈接:
link /entry:myentry /subsystem:console myentrytest.obj kernel32.lib
最終得到可執行文件myentrytest.exe。
執行效果與printf出來的效果相同,但是其中用到的原理卻是很不一樣的。
這裡,我們就接觸到了三個函數,這三個函數可以不通過CRT庫直接使用,並且不造成任何問題,這三個函數都是所謂的Windows API。這三個API都是kernel32提供的。通過直接調用windows API,可以使用到操作系統的功能,並成功繞過CRT庫。盡管我們平時不太會使用到這樣的技巧,但是有時接觸到這樣的代碼或自己編碼時有這樣的要求,也是可能的。當然,要完全繞過CRT庫,就需要提取出所編寫程序要使用到CRT庫提供功能的所有函數,並使用windows API來同等代替,這樣花費的時間和重復做輪子也沒什麼兩樣,不過,如果要真的對系統有一定了解,還是有一定意義的。
這裡介紹一下windows API:
視窗操作系統應用程序接口(Windows API),有非正式的簡稱法為WinAPI,是微軟對於Windows操作系統中可用的核心應用程序編程接口的稱法。它被設計為各種語言的程序調用,也是應用軟件與Windows系統最直接的交互方式。大多數驅動程序所需要的對Windows系統的更底層次訪問接口,由所用版本的Windows的Native API來提供接口。
Windows有一個軟件開發包(SDK, software development kit)提供相應的文檔和工具,以使程序員開發使用Windows API的軟件和利用Windows技術。
Windows API所提供的功能可以歸為七類:[4]
基礎服務(Base Services)[5],提供對Windows系統可用的基礎資源的訪問接口。比如象:文件系統(file system)、外部設備(device)、,行程(process)、線程(thread)以及訪問注冊表(Windows registry)和錯誤處理機制(error handling)。這些功能接口位於,16位元Windows下的kernel.exe、krnl286.exe或krnl386.exe系統文件中;以及32位元Windows下的 kernel32.dll和advapi32.dll中。
圖形設備接口(GDI)[6],提供功能為:輸出圖形內容到顯示器、打印機以及其他外部輸出設備。它位於16位元Windows下的gdi.exe;以及32位元Windows下的gdi32.dll。
圖形化用戶界面(GUI)[7],提供的功能有創建和管理屏幕和大多數基本控件(control),比如按鈕和滾動條。接收鼠標和鍵盤輸入,以及其他與GUI有關的功能。這些調用接口位於:16位元Windows下的user.exe,以及32位元Windows下的user32.dll。從Windows XP版本之後,基本控件和通用對話框控件(Common Control Library)的調用接口放在comctl32.dll中。
通用對話框鏈接庫(Common Dialog Box Library)[8],為應用程序提供標准對話框,比如打開/保存文件對話框、顏色對畫框和字體對話框等等。這個鏈接庫位於:16位元Windows下的commdlg.dll中,以及32位元Windows下comdlg32.dll中。它被歸類為User Interface API之下。
通用控件鏈接庫(Common Control Library)[9],為應用程序提供接口來訪問操作系統提供的一些高級控件。比如像:狀態欄(status bar)、進度條(progress bars)、工具欄(toolbar)和標簽(tab)。這個鏈接庫位於:16位元Windows下的commctrl.dll中,以及32位元Windows下comctl32.dll中。。它被歸類為User Interface API之下。
Windows外殼(Windows Shell)[10][11],作為Windows API的組成部分,不僅允許應用程序訪問操作系統shell提供的功能,還對之有所改進和增強。它位於16位元Windows下的shell.dll中,以及32位元Windows下的shell32.dll中(Windows 95則在 shlwapi.dll中)。 它被歸類為User Interface API之下。
網絡服務(Network Services)[12],為訪問操作系統提供的多種網絡 功能提供接口。它包括NetBIOS、Winsock、NetDDE及RPC等。