,因為其包含了眾多的API函數聲明頭文件。為了探究這個小小的MessageBox是怎么彈出來的,我們右擊MessageBox,選擇“GotodefinitionofMessageBox(轉到定義)”將打開

亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

由MessageBox透視Win32 API的調用

系統 1976 0

下面我們來看看 Windows 平臺下應用程序是怎么調用 Windows 提供的底層 API 服務運行的。

我們編寫 Win32SDK 程序時,需要彈出對話框以作出友好的選擇, MessageBox 這個 API 函數就可以實現該功能。在開頭要添加 <windows.h> 因為其包含了眾多的 API 函數聲明頭文件。為了探究這個小小的 MessageBox 是怎么彈出來的,我們右擊 MessageBox ,選擇“ Go to definition of MessageBox( 轉到定義 ) ”將打開 <winuser.h> MessageBox 定義處。 MessageBox(A/W) 的函數原型聲明如下:

// WINUSER.H

WINUSERAPI

int

WINAPI

MessageBoxA (

HWND hWnd ,

LPCSTR lpText ,

LPCSTR lpCaption ,

UINT uType );

WINUSERAPI

int

WINAPI

MessageBoxW (

HWND hWnd ,

LPCWSTR lpText ,

LPCWSTR lpCaption ,

UINT uType );

#ifdef UNICODE

#define MessageBox MessageBoxW

#else

#define MessageBox MessageBoxA

#endif // !UNICODE

我們在使用 Windows 窗口操作系統時,經常會蹦出大大小小的 窗口, MessageBox 只是 Windows 作為提示的對話框窗口單元。那么, MessageBoxW 這個 API 函數到底在哪里實現的呢?應用程序是如何調用系統接口函數的呢?

動態鏈接庫( .dll

初窺 DLL

實際上 Windows API 函數是定義在一些 DLL 中的, DLL 實現了代碼封裝,從這個角度來看 DLL 才是真正意義上的 API 函數包,它是非開源 Windows 操作系統提供給我們的底層接口。 DLL 的編制與具體的編程語言及編譯器無關。

動態鏈接庫 dll 文件( Linux 中與之對應的是的 .so 存放在 C:/WINDOWS/system 目錄和 C:/WINDOWS/system32 目錄下,它在被應用程序調用時才同程序相鏈接。

其中 Windows 系統最重要的 DLL User32.dll Gdi32.dll Kernel32.dll 這三個庫文件。這三個庫文件中的 API 函數大都在頭文件 <windows.h> 中進行了聲明。從功能上進行分類, User32.dll Windows XP USER API Client DLL )定義了窗口管理函數,包括窗口的創建、顯示、設置和移動等; Gdi32.dll GDI Client DLL )定義了圖形設備函數( GDI ),實現與設備無關的繪圖功能; Kernel32.dll Windows NT BASE API Client DLL )定義了系統服務函數,包括諸如內存調度、進程管理等與操作系統有關的底層功能。我們可以通過三種方式來查看 DLL 文件中的導出函數信息:( 1 )使用 Windows 系統的 dumpbin 命令(在命令行中: C:/WINDOWS/system32> dumpbin ntdll.dll /exports );( 2 )使用 VC 自帶的 Depends 工具( Microsoft Visual Studio 6.0 Tools à Depends Visual Studio 2005 命令行提示 à depends );( 3 Dll 函數查看器 ViewDll ExeScope )。以下使用 VC 自帶的 Depends 工具查看 user32.dll MessageBox 函數系列。

由MessageBox透視Win32 API的調用

DLL API

正如 Java 的跨平臺( Write Once, Run Everywhere )需要 JVM 的支持一樣, C/C++ 成為跨平臺的編程語言,依賴各個平臺(包括操作系統和編譯器)對 C/C++ 標準函數庫的具體平臺實現。

VS 編譯器自帶的標準 C 函數庫 <stdio.h> <stdlib.h> <string.h> <math.h> 中聲明的函數可以到 C:/Program Files/Microsoft Visual Studio/VC98/CRT/SRC( C:/Program Files/Microsoft Visual Studio 8/VC/crt/src) 中查看相關實現源代碼。 strcat.c 文件提供了 strcat strcpy 函數的源碼 , Windows 系統中, C: / WINDOWS/system32/ ntdll.dll 提供了 strcat strcpy 這兩個 CRT API 的底層實現。用戶對 C 函數的調用最終通過調用底層 API 來完成真正的功能。例如 C 標準庫函數 create 用于創建文件,但它是靠調用 CreateFile kernel32.dll 函數來完成創建文件功能的; beginthread( process.h,thread.c ) 需要調用 CreateThread kernel32.dll 函數來完成線程的創建。

DLL 的移植升級

Windows 將遵循下面的搜索順序來定位 DLL : 包含 EXE 文件的目錄 > 進程的當前工作目錄 >Windows 系統目錄 >Windows 目錄 > 列在 Path 環境變量中的一系列目錄。

如果你在本機編寫一個 Windows 應用程序,移植到其他機子上 ( 當然也是 Windows 操作系統 ) ,有可能因為缺少相關 DLL 文件而無法執行。因為 DLL 是動態鏈接,就是隨用隨加載,這就是為什么我們玩 3D 游戲時經常彈出缺少 d3dx9***.dll 的錯誤提示。如果啟動的程序調用了一個過期的 DLL 文件或不匹配的 DLL 文件,則會出現“未定義的動態鏈接調用”消息。

動態鏈接庫除了實現代碼的共享外,其模塊封裝特性使得應用程序在調用一個 DLL 的不同版本時,只要導出的函數名相同就不必進行重新編譯鏈接。這樣,軟件產品在更新或升級時,客戶程序不必進行改動。在開發軟件產品時,對于通用功能的函數,一般以 DLL 的形式來實現。 Windows 設備驅動程序就是體現上述特點的動態鏈接庫。

DLL 的調用

動態鏈接庫的調用方式又分為隱式調用(也稱靜態調用,需要 .lib 文件)和顯式調用(也稱動態調用, LoadLibrary à GetProcAddress à FreeLibrary )。

那么,在我們編寫的程序中,如何調用 DLL 中的 API 呢?既然用戶對 C 函數的調用最終是通過調用底層 API 來完成真正的功能,那么,我們在編寫第一個 Hello World 程序時就已經不知不覺地調用了 DLL 。實際上 <stdio.h> 中定義的 printf 函數由 msvcrt.dll 函數導出,而 *printf 系列函數在 ntdll.dll 中有具體底層實現。

DLL 文件包括了具體實現的代碼編譯后的結果(二進制的機器碼),而頭文件中的代碼主要是 DLL 庫文件 導出函數的原型聲明。 <winuser.h> 即主要對 user32.dll 中導出的函數做聲明索引, 所以若要使用 MessageBox(A/W) #include <winuser.h> (已被 <windows.h> 包含)。正如調用 printf 函數需要 #include <stdio.h>

在調用 printf 函數或 MessageBox 函數時,我們僅僅包含了聲明頭文件,沒有顯式 LoadLibrary à GetProcAddress ,那我們是如何是隱式調用(定位) DLL 中的 API 的呢?實際上我們在利用 VC 向導生成一個 Win32 Console Application 時,向導已經為項目設置了 link 項( Project Settings à Link à Input à Object/library modules ),其中默認鏈接 kernel32.lib user32.lib gdi32.lib 等。

靜態鏈接庫( .lib

目標代碼集靜態鏈接庫

在早期庫的組織形式相對簡單,里面的目標代碼只能夠進行靜態鏈接,所以我們稱為“靜態庫”,靜態庫的結構比較簡單,其實就是把原來的目標代碼( *.obj) 集合在一起,鏈接程序 LINKER 根據每一份目標代碼的符號表查找相應的符號(函數和變量的名字),找到的話就把該函數里面需要定位的進行定位,然后將整塊函數代碼放進可執行文件里,若是找不到需要的函數就報錯退出。標準 Turbo C2.0 中的 C 庫函數,例如 scanf printf memcpy strcpy 等,就是使用的靜態庫技術。

以下是 C 程序的編譯鏈接過程: (1) 執行 cl /c main.c;cl /c lib1.c;cl /c lib2.c 生成了 main.obj lib1.obj lib2.obj 三個文件; (2) 執行 link /lib lib1.obj;link /lib lib2.obj 生成了 2 個文件 lib1.lib lib2.lib (3) 執行 link main.obj lib1.lib lib2.lib 生成 main.exe

靜態鏈接 lib 庫( Linux 中與之對應的是的 .a 的兩個特點:

1 )鏈接后產生的可執行文件包含了所有需要調用的函數的代碼,因此占用磁盤空間較大。

2 )如果有多個(調用相同庫函數的)進程在內存中同時運行,內存中就存有多份相同的庫函數代碼,因此占用內存空間較多。

DLL 隱式調用靜態鏈接庫

使用 DLL 隱式鏈接時,可執行程序鏈接到一個包含 DLL 導出函數信息的輸入庫文件 (.LIB 文件 ) 。操作系統在加載使用可執行程序時加載 DLL 。可執行程序直接通過函數名像調用其他源文件中的函數一樣調用 DLL 中的導出函數。

我們可以用記事本打開 C:/Program Files/Microsoft Visual Studio/VC98/Lib 中的 USER32.LIB 文件,其中有

__imp__MessageBoxA@16_ MessageBoxW @16 // 這里 16 為參數的字節數

? _ MessageBoxW @16 USER32.dll USER32.dll/ 889206797

靜態鏈接庫 lib 文件中存放的是接口函數的入口地址, dll 中存放的是函數實體。當我們隱式調用 dll 時,需要在 Link 選項指明其對應的 lib 庫。 lib 告訴編譯器你的 dll 都導出了什么函數,以及這些函數的相對地址,運行的時候就根據這些信息就可以找到 dll 中相應的 API

除了在“ Project Settings à Link à Input à object/library modules” 中填寫靜態鏈接庫( *.lib )外,我們還可以通過 #pragma comment 宏顯示輸入 *.lib 庫文件, 例如在網絡編程中需要添加 WS2_32.LIB 庫,則可以在文件的開頭包含頭文件后 #pragma comment ( lib , "WS2_32.LIB" ) 引入靜態鏈接庫文件。

由于 我們 經常 要調用一些第三方廠商或其他編譯器編寫的動態鏈接庫,但是一般都不提供源文件或 .lib 文件。我們若知道相應 API 的函數原型,通過 LoadLibrary à GetProcAddress 以實現正確的調用。如果隱式調用,則需要 lib 文件,可使用 DLL2LIB 工具生成 DLL 對應的 LIB 文件。

在編寫 MFC 項目時,我們打開 Project Settings à General Microsoft Foundation Classes 里面有兩種鏈接方式: Use MFC in a Static Library Use MFC in a Shared Library 。對應在 Visual Studio 2005 中“項目屬性 à 配置屬性 à 常規 à MFC 的使用”中設置鏈接方式。

如果選擇 Use MFC in a Shared Library 的話,你編譯后的程序中不包含 MFC 庫,所以文件會比較小,但是如果你的程序直接移到一個沒有安裝過 MFC 的機器上時,可能會導致找不到 MFC DLL ,故發布時要帶 MFC DLL 文件。如果選擇 Use MFC in a Static Library ,那么編譯后的程序就直接包含了 MFC 的靜態鏈接庫(目標代碼集,相當于基于源碼級集成),文件可能會大一些,但是可以直接移到其他機器上運行,即發布時不用帶 MFC DLL 文件。

參考:

動態鏈接庫 DLL 的創建和使用

深入探究 VC- 編譯 CL.EXE

隱式 鏈接 無.LIB 動態鏈

由MessageBox透視Win32 API的調用


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 亚洲综合一区二区精品久久 | 国产免费不卡 | 久久人人网| 性做久久久久久久免费看 | 欧美成人免费高清网站 | 国产成人福利夜色影视 | 五月激情综合婷婷 | 国产亚洲女在线精品 | 韩国欧美一级毛片免费 | 91福利在线免费观看 | 久久久久国产精品免费 | 蕾丝视频永久在线入口香蕉 | 成人在线免费小视频 | 高清国产美女在线观看 | 欧美日韩国产亚洲一区二区 | 日本aaaa毛片在线看 | 欧美 亚洲 一区 | 男人的天堂视频在线 | 久操视频在线播放 | 久久99爱视频 | 天天弄天天干 | 久草久热 | 亚洲精品一区二区伦理 | 国产精品探花一区在线观看 | 久一在线视频 | 久久婷婷五月综合色丁香 | 久久精品中文字幕有码日本 | 天天操免费视频 | 亚洲性生活 | 久久久久久久久中文字幕 | 亚洲高清成人 | 国产精品每日更新 | 五月天激情在线 | 写真福利 第 页 在线视频 | 精品视频久久久 | 国产综合视频在线 | 亚洲一区二区三区精品影院 | 亚洲十欧美十日韩十国产 | 久久国产热这里只有精品 | 日日噜噜夜夜狠视频免费 | 日本精品一区二区三区在线观看 |