版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、VC+動態(tài)鏈接庫動態(tài)鏈接庫(DLL)編程編程1.概論概論 先來論述一下先來論述一下DLL(Dynamic Linkable Library)的概念,你可以簡單的把的概念,你可以簡單的把DLL看成一種倉庫,它提供給你一些可以直看成一種倉庫,它提供給你一些可以直接拿來用的變量、函數(shù)或類。接拿來用的變量、函數(shù)或類。在倉庫的開展史上經(jīng)歷了在倉庫的開展史上經(jīng)歷了“無庫靜態(tài)鏈無庫靜態(tài)鏈接庫動態(tài)鏈接庫的時代。接庫動態(tài)鏈接庫的時代。 對動態(tài)鏈接庫,需建立如下概念:對動態(tài)鏈接庫,需建立如下概念: 1與詳細的編程語言及編譯器無關(guān)與詳細的編程語言及編譯器無關(guān) 只要遵循約定的只要遵循約定的DLL接口規(guī)范和調(diào)用方接口規(guī)
2、范和調(diào)用方式,用各種語言編寫的式,用各種語言編寫的DLL都可以互相都可以互相調(diào)用。調(diào)用。譬如譬如Windows提供的系統(tǒng)提供的系統(tǒng)DLL其中包其中包括了括了Windows的的API,在任何開發(fā)環(huán)境,在任何開發(fā)環(huán)境中都能被調(diào)用,不在乎其是中都能被調(diào)用,不在乎其是Visual Basic、Visual C+還是還是Delphi。 2動態(tài)鏈接庫隨處可見動態(tài)鏈接庫隨處可見 在在Windows目錄下的目錄下的system32文件夾中文件夾中會看到會看到kernel32.dll、user32.dll和和gdi32.dll,windows的大多數(shù)的大多數(shù)API都包含都包含在這些在這些DLL中。中。kerne
3、l32.dll中的函數(shù)主要處置內(nèi)存管理中的函數(shù)主要處置內(nèi)存管理和進程調(diào)度;和進程調(diào)度;user32.dll中的函數(shù)主要控制用戶界面中的函數(shù)主要控制用戶界面(MessageBox函數(shù)函數(shù));gdi32.dll中的函數(shù)那么負責(zé)圖形方面的操中的函數(shù)那么負責(zé)圖形方面的操作。作。 (3)VC動態(tài)鏈接庫的分類動態(tài)鏈接庫的分類Visual C+支持三種支持三種DLL,它們分別是非,它們分別是非MFC動動態(tài)庫、態(tài)庫、MFC規(guī)那么規(guī)那么DLL、MFC Extension DLL。 非非MFC動態(tài)庫不采用動態(tài)庫不采用MFC類庫構(gòu)造,其導(dǎo)出函類庫構(gòu)造,其導(dǎo)出函數(shù)為規(guī)范的數(shù)為規(guī)范的C接口,能被非接口,能被非MFC或或
4、MFC編寫的應(yīng)編寫的應(yīng)用程序所調(diào)用;用程序所調(diào)用;MFC規(guī)那么規(guī)那么DLL 包含一個繼承自包含一個繼承自CWinApp的類,的類,但其無消息循環(huán);但其無消息循環(huán);MFC擴展擴展DLL采用采用MFC的動態(tài)鏈接版本創(chuàng)建,的動態(tài)鏈接版本創(chuàng)建,它只能被用它只能被用MFC類庫所編寫的應(yīng)用程序所調(diào)用。類庫所編寫的應(yīng)用程序所調(diào)用。 2.靜態(tài)鏈接庫靜態(tài)鏈接庫 在在VC+6.0中中new一個名稱為一個名稱為libTest的的static library工程工程,并新建并新建lib.h和和lib.cpp兩個文件,兩個文件,lib.h和和lib.cpp的源代碼的源代碼如下:如下: /文件:文件:lib.h #ifn
5、def LIB_H #define LIB_H extern C int add(int x,int y);/聲明為聲明為C編譯、連編譯、連接方式的外部函數(shù)接方式的外部函數(shù) #endif /文件:文件:lib.cpp #include lib.h int add(int x,int y) return x + y; #include #include .lib.h #pragma comment( lib, .debuglibTest.lib ) /指定與靜態(tài)庫指定與靜態(tài)庫一起連接一起連接 int main(int argc, char* argv) printf( 2 + 3 = %d, a
6、dd( 2, 3 ) ); 選擇選擇tools、options、directories、library files菜單菜單或選項,填入庫文件途徑或選項,填入庫文件途徑 4.非非MFC DLL 在建立的工程中添加在建立的工程中添加lib.h及及l(fā)ib.cpp文件,源代碼文件,源代碼如下:如下:/* 文件名:文件名:lib.h*/#ifndef LIB_H#define LIB_Hextern C int _declspec(dllexport)add(int x, int y);#endif/* 文件名:文件名:lib.cpp*/#include lib.hint add(int x, int
7、y)return x + y;dllCall #include #include typedef int(*lpAddFun)(int, int); /宏定義函數(shù)指針類型宏定義函數(shù)指針類型int main(int argc, char *argv) HINSTANCE hDll; /DLL句柄句柄 lpAddFun addFun; /函數(shù)指針函數(shù)指針 hDll = LoadLibrary(.DebugdllTest.dll); if (hDll != NULL) addFun = (lpAddFun)GetProcAddress(hDll, add); if (addFun != NULL)
8、int result = addFun(2, 3); printf(%d, result); FreeLibrary(hDll); return 0;DLL的調(diào)用和靜態(tài)鏈接庫的調(diào)用有較大差別的調(diào)用和靜態(tài)鏈接庫的調(diào)用有較大差別 首先,語句首先,語句typedef int ( * lpAddFun)(int,int)定義了一個與定義了一個與add函數(shù)接受參數(shù)類型和返回值均一樣的函數(shù)指針類型。隨函數(shù)接受參數(shù)類型和返回值均一樣的函數(shù)指針類型。隨后,在后,在main函數(shù)中定義了函數(shù)中定義了lpAddFun的實例的實例addFun;其次,在函數(shù)其次,在函數(shù)main中定義了一個中定義了一個DLL HINST
9、ANCE句柄實句柄實例例hDll,通過,通過Win32 Api函數(shù)函數(shù)LoadLibrary動態(tài)加載了動態(tài)加載了DLL模塊并將模塊并將DLL模塊句柄賦給了模塊句柄賦給了hDll;再次,在函數(shù)再次,在函數(shù)main中通過中通過Win32 Api函數(shù)函數(shù)GetProcAddress得得到了所加載到了所加載DLL模塊中函數(shù)模塊中函數(shù)add的地址并賦給了的地址并賦給了addFun。經(jīng)由函數(shù)指針經(jīng)由函數(shù)指針addFun進展了對進展了對DLL中中add函數(shù)的調(diào)用;函數(shù)的調(diào)用;最后,應(yīng)用工程使用完最后,應(yīng)用工程使用完DLL后,在函數(shù)后,在函數(shù)main中通過中通過Win32 Api函數(shù)函數(shù)FreeLibrary
10、釋放了已經(jīng)加載的釋放了已經(jīng)加載的DLL模塊。模塊。聲明導(dǎo)出函數(shù)聲明導(dǎo)出函數(shù) DLL中導(dǎo)出函數(shù)的聲明有兩種方式:中導(dǎo)出函數(shù)的聲明有兩種方式:一種為給出的在函數(shù)聲明中加上一種為給出的在函數(shù)聲明中加上_declspec(dllexport);一種方式是采用模塊定義一種方式是采用模塊定義(.def) 文件聲明文件聲明;在在DLL中想要中想要export的函數(shù)和數(shù)據(jù)定義的函數(shù)和數(shù)據(jù)定義前添加前添加_declspecdllexport關(guān)鍵字關(guān)鍵字對于函數(shù)和變量定義,加在最前面;對于函數(shù)和變量定義,加在最前面;對于對于class定義,加在定義,加在class關(guān)鍵字后關(guān)鍵字后;_declspec(dllexp
11、ort) void ShowDlg(void)class _declspec(dllexport) class_name /導(dǎo)導(dǎo)出類出類 這樣該函數(shù)和數(shù)據(jù)就會被添加到這樣該函數(shù)和數(shù)據(jù)就會被添加到ET中。中。使用這種方法函數(shù)將按名字使用這種方法函數(shù)將按名字export。_declspec(dllexport)(.def) 文件聲明文件聲明 為為DLL創(chuàng)建一個創(chuàng)建一個.DEF文件模塊定義文件模塊定義文件,并在文件,并在build該該DLL時使用這時使用這個個.DEF文件。使用這種方法使你可以文件。使用這種方法使你可以將函數(shù)按序號將函數(shù)按序號export。 在在LINK選項卡中假設(shè):選項卡中假設(shè):
12、/def:lib.def 將將lib.def參與到工程中。參與到工程中。lib.def; lib.def : 導(dǎo)出導(dǎo)出DLL函數(shù)函數(shù)LIBRARY dllTestEXPORTSadd 1.def文件的規(guī)那么為:文件的規(guī)那么為:(1)LIBRARY語句說明語句說明.def文件相應(yīng)的文件相應(yīng)的DLL;(2)EXPORTS語句后列出要導(dǎo)出函數(shù)的名稱。語句后列出要導(dǎo)出函數(shù)的名稱??梢栽诳梢栽?def文件中的導(dǎo)出函數(shù)名后加文件中的導(dǎo)出函數(shù)名后加n,表示要導(dǎo),表示要導(dǎo)出函數(shù)的序號為出函數(shù)的序號為n在進展函數(shù)調(diào)用時,這個序號在進展函數(shù)調(diào)用時,這個序號將發(fā)揮其作用;將發(fā)揮其作用;(3).def 文件中的注釋由
13、每個注釋行開場處的文件中的注釋由每個注釋行開場處的分號分號 (;) 指定,且注釋不能與語句共享一行。指定,且注釋不能與語句共享一行。庫的調(diào)試與查看庫的調(diào)試與查看 動態(tài)鏈接庫中的導(dǎo)出接口可以使用動態(tài)鏈接庫中的導(dǎo)出接口可以使用Visual C+的的Depends工具進展查看,工具進展查看,用用Depends翻開系統(tǒng)目錄中的翻開系統(tǒng)目錄中的MouseHook.dll .DLL的調(diào)用方式的調(diào)用方式 隱式調(diào)用隱式調(diào)用: 將將DLL工程生成的工程生成的.lib文件和文件和.dll文件拷文件拷入當(dāng)前工程所在的目錄,并在入當(dāng)前工程所在的目錄,并在*.cpp文文件的頂部添加:件的頂部添加: #pragma co
14、mment(lib,RegularDll.lib) OR動態(tài)調(diào)用動態(tài)調(diào)用特點特點:是完全由編程者用是完全由編程者用 API 函數(shù)加載和函數(shù)加載和卸載卸載 DLL,程序員可以決定,程序員可以決定 DLL 文件文件何時加載或不加載,顯式鏈接在運行時何時加載或不加載,顯式鏈接在運行時決定加載哪個決定加載哪個 DLL 文件。文件。dllTest.dll 在建立的工程中添加在建立的工程中添加lib.h及及l(fā)ib.cpp文件,源代碼如下:文件,源代碼如下:/* 文件名:文件名:lib.h*/#ifndef LIB_H#define LIB_Hextern C int _declspec(dllexport
15、)add(int x, int y);#endif/* 文件名:文件名:lib.cpp*/#include lib.hint add(int x, int y)return x + y;調(diào)用調(diào)用 dllTest.dll #include #include typedef int(*lpAddFun)(int, int); /宏定義函數(shù)指針類型宏定義函數(shù)指針類型int main(int argc, char *argv) HINSTANCE hDll; /DLL句柄句柄 lpAddFun addFun; /函數(shù)指針函數(shù)指針hDll = LoadLibrary(.DebugdllTest.dll)
16、;if (hDll != NULL) addFun = (lpAddFun)GetProcAddress(hDll, add);if (addFun != NULL)int result = addFun(2, 3);printf(%d, result);FreeLibrary(hDll); DLL的的Export和和Import DLL的的export是指將是指將DLL中的函數(shù)和數(shù)據(jù)輸出中的函數(shù)和數(shù)據(jù)輸出到其它程式中,以供其使用。到其它程式中,以供其使用。DLL的的import是是指使用指使用DLL的程式引入的程式引入DLL中的函數(shù)和數(shù)據(jù)。中的函數(shù)和數(shù)據(jù)。DLL的的export DLL中包含
17、有一個表,稱為中包含有一個表,稱為export table以下簡稱以下簡稱ET,其中包含了,其中包含了DLL中可以被外部程式使用的所有函數(shù)和數(shù)據(jù)中可以被外部程式使用的所有函數(shù)和數(shù)據(jù)的名字。的名字。只要記錄在只要記錄在ET中的函數(shù)和數(shù)據(jù)才可以被外部中的函數(shù)和數(shù)據(jù)才可以被外部程式所使用假如沒有程式所使用假如沒有.DEF文件的話,其它文件的話,其它所有沒有記錄在所有沒有記錄在ET中的函數(shù)和數(shù)據(jù)都被視為中的函數(shù)和數(shù)據(jù)都被視為是是DLL私有的。私有的。DllMain函數(shù)函數(shù) Windows在加載在加載DLL的時候,需要一個入口函的時候,需要一個入口函數(shù),就好像控制臺或數(shù),就好像控制臺或DOS程序需要程序
18、需要main函數(shù)、函數(shù)、WIN32程序需要程序需要WinMain函數(shù)一樣。函數(shù)一樣。在前面的例子中,在前面的例子中,DLL并沒有提供并沒有提供DllMain函函數(shù),應(yīng)用工程也能勝利引用數(shù),應(yīng)用工程也能勝利引用DLL,這是因為,這是因為Windows在找不到在找不到DllMain的時候,系統(tǒng)會從的時候,系統(tǒng)會從其它運行庫中引入一個不做任何操作的缺省其它運行庫中引入一個不做任何操作的缺省DllMain函數(shù)版本,并不意味著函數(shù)版本,并不意味著DLL可以放棄可以放棄DllMain函數(shù)。函數(shù)。 BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_
19、for_call, LPVOID lpReserved) DllMain函數(shù)在函數(shù)在DLL被加載和卸載時被調(diào)用,在單個線程啟動和終止時,被加載和卸載時被調(diào)用,在單個線程啟動和終止時,DLLMain函數(shù)也被調(diào)用函數(shù)也被調(diào)用; ul_reason_for_call指明了被調(diào)用的原因。原因共有指明了被調(diào)用的原因。原因共有4種,即種,即PROCESS_ATTACH、PROCESS_DETACH、THREAD_ATTACH和和THREAD_DETACH,以,以switch語句列出。語句列出。DLL導(dǎo)出變量導(dǎo)出變量 /* 文件名:文件名:lib.h*/#ifndef LIB_H#define LIB_He
20、xtern int dllGlobalVar;#endif/* 文件名:文件名:lib.cpp */#include lib.h#include int dllGlobalVar;BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) dllGlobalVar = 100; /在在dll被加載時,賦全局變量為被加載時,賦全局變量為100 return TRUE;文件名:文件名:lib.def;在在DLL中導(dǎo)出變量中導(dǎo)出變量LIBRARY dllTestEXPORTSdllGlobalV
21、ar DATA 在主函數(shù)中引用在主函數(shù)中引用DLL中定義的全局變量:中定義的全局變量:#include #pragma comment(lib,dllTest.lib)extern int _declspec(dllimport) dllGlobalVar; /用用_declspec(dllimport)導(dǎo)入導(dǎo)入int main(int argc, char *argv)printf(%d , dllGlobalVar);dllGlobalVar = 1; printf(%d , dllGlobalVar);return 0;特別要注意特別要注意用用extern int dllGlobalVa
22、r聲明所導(dǎo)入的并不是聲明所導(dǎo)入的并不是DLL中全局變量自身,而是其地址,應(yīng)用程序中全局變量自身,而是其地址,應(yīng)用程序必需通過強迫指針轉(zhuǎn)換來使用必需通過強迫指針轉(zhuǎn)換來使用DLL中的全局變中的全局變量。這一點,從量。這一點,從*(int*)dllGlobalVar可以看出??梢钥闯?。因而在采用這種方式引用因而在采用這種方式引用DLL全局變量時,千全局變量時,千萬不要進展這樣的賦值操作:萬不要進展這樣的賦值操作:dllGlobalVar = 1;MFC規(guī)那么規(guī)那么DLL MFC規(guī)那么規(guī)那么DLL的概念表達在兩方面:的概念表達在兩方面:它是它是MFC的的 “是是MFC的意味著可以在這種的意味著可以在這
23、種DLL的內(nèi)部使的內(nèi)部使用用MFC;它是規(guī)那么的它是規(guī)那么的 “是規(guī)那么的意味著它不同于是規(guī)那么的意味著它不同于MFC擴展擴展DLL,在在MFC規(guī)那么規(guī)那么DLL的內(nèi)部雖然可以使用的內(nèi)部雖然可以使用MFC,但是其與應(yīng)用程序的接口不能是但是其與應(yīng)用程序的接口不能是MFC。而。而MFC擴展擴展DLL與應(yīng)用程序的接口可以是與應(yīng)用程序的接口可以是MFC,可以從可以從MFC擴展擴展DLL中導(dǎo)出一個中導(dǎo)出一個MFC類的派類的派生類。生類。Regular DLL可以被所有支持可以被所有支持DLL技術(shù)的語言技術(shù)的語言所編寫的應(yīng)用程序調(diào)用,當(dāng)然也包括使用所編寫的應(yīng)用程序調(diào)用,當(dāng)然也包括使用MFC的應(yīng)用程序。的應(yīng)
24、用程序。 Regular DLL分為兩類:分為兩類: 1靜態(tài)鏈接到靜態(tài)鏈接到MFC 的規(guī)那么的規(guī)那么DLL 靜態(tài)鏈接到靜態(tài)鏈接到MFC的規(guī)那么的規(guī)那么DLL與與MFC庫包括庫包括MFC擴展擴展 DLL靜態(tài)鏈接,將靜態(tài)鏈接,將MFC庫的代碼直接生成在庫的代碼直接生成在.dll文件中。文件中。在調(diào)用這種在調(diào)用這種DLL的接口時,的接口時,MFC使用使用DLL的資源。因而,的資源。因而,在靜態(tài)鏈接到在靜態(tài)鏈接到MFC 的規(guī)那么的規(guī)那么DLL中不需要進展模塊狀態(tài)的中不需要進展模塊狀態(tài)的切換。切換。 使用這種方法生成的規(guī)那么使用這種方法生成的規(guī)那么DLL其程序較大,也可能包含反其程序較大,也可能包含反復(fù)
25、的代碼。復(fù)的代碼。 2動態(tài)鏈接到動態(tài)鏈接到MFC 的規(guī)那么的規(guī)那么DLL 動態(tài)鏈接到動態(tài)鏈接到MFC 的規(guī)那么的規(guī)那么DLL 可以和使用它的可執(zhí)行文件可以和使用它的可執(zhí)行文件同時動態(tài)鏈接到同時動態(tài)鏈接到 MFC DLL 和任何和任何MFC擴展擴展 DLL。在使用。在使用了了MFC共享庫的時候,默認情況下,共享庫的時候,默認情況下,MFC使用主應(yīng)用程序使用主應(yīng)用程序的資源句柄來加載資源模板。這樣,當(dāng)?shù)馁Y源句柄來加載資源模板。這樣,當(dāng)DLL和應(yīng)用程序中存和應(yīng)用程序中存在一樣在一樣ID的資源時即所謂的資源反復(fù)問題,系統(tǒng)可能不的資源時即所謂的資源反復(fù)問題,系統(tǒng)可能不能獲得正確的資源。因而,對于共享能獲
26、得正確的資源。因而,對于共享MFC DLL的規(guī)那么的規(guī)那么DLL,必需進展模塊切換以使得,必需進展模塊切換以使得MFC可以找到正確的資源可以找到正確的資源模板。模板。MFC規(guī)那么規(guī)那么DLL的創(chuàng)建的創(chuàng)建 automation自動化技術(shù)自動化技術(shù) 是否支持是否支持Windows Sockets 在在MFC應(yīng)用程序中應(yīng)用程序中CWinApp取代了取代了SDK程序中程序中WinMain的地位,的地位,SDK程序程序WinMain所完成的工作由所完成的工作由CWinApp的三的三個函數(shù)完成:個函數(shù)完成:virtual BOOL InitApplication( );virtual BOOL InitI
27、nstance( );virtual BOOL Run( ); /傳說中傳說中MFC程程序的序的“活水源頭活水源頭MFC規(guī)那么規(guī)那么DLL接口函數(shù)接口函數(shù) #include StdAfx.h #include DllDialog.h _declspec(dllexport) void ShowDlg(void) 或或 extern C _declspec(dllexport) void ShowDlg(void) CDllDialog dllDialog; dllDialog.DoModal(); 分析:分析: 這個接口并不使用這個接口并不使用MFC,但是在其中卻可以調(diào)用,但是在其中卻可以調(diào)用
28、MFC擴展類擴展類CdllDialog的函數(shù),這表達了的函數(shù),這表達了“規(guī)那么的概類。規(guī)那么的概類。 與非與非MFC DLL完全一樣,可以使用完全一樣,可以使用_declspec(dllexport)聲明聲明或在或在.def中引出的方式導(dǎo)出中引出的方式導(dǎo)出MFC規(guī)那么規(guī)那么DLL中的接口。中的接口。MFC規(guī)那么規(guī)那么DLL的調(diào)用的調(diào)用 #pragma comment(lib,RegularDll.lib)_declspec(dllexport) void ShowDlg(void)void ShowDlg(void); 或或extern C _declspec(dllexport) void
29、ShowDlg(void)extern C void ShowDlg(void); void CRegularDllCallDlg:OnCalldllButton() ShowDlg();MFC擴展擴展 DLL MFC擴展擴展DLL與與MFC規(guī)那么規(guī)那么DLL的一樣點在于在兩種的一樣點在于在兩種DLL的內(nèi)部都可以使用的內(nèi)部都可以使用MFC類庫,其不同點在于類庫,其不同點在于MFC擴展擴展DLL與應(yīng)用程序的接口可以是與應(yīng)用程序的接口可以是MFC的。的。 MFC擴展擴展DLL的含義在于它是的含義在于它是MFC的擴展,其主要功的擴展,其主要功能是實現(xiàn)從現(xiàn)有能是實現(xiàn)從現(xiàn)有MFC庫類中派生出可重用的類。
30、庫類中派生出可重用的類。 MFC擴展擴展DLL使用使用MFC 動態(tài)鏈接庫版本,因而只要動態(tài)鏈接庫版本,因而只要用共享用共享MFC 版本生成的版本生成的MFC 可執(zhí)行文件應(yīng)用程序可執(zhí)行文件應(yīng)用程序或規(guī)那么或規(guī)那么DLL才干使用才干使用MFC擴展擴展DLL。 一般使用一般使用MFC擴展擴展DLL來包含一些來包含一些MFC的加強功能,的加強功能,譬如擴展譬如擴展MFC的的CStatic、CButton等類使之具備更強等類使之具備更強大的才干。大的才干。三種三種DLL對對DllMain入口函數(shù)的不同處置方式:入口函數(shù)的不同處置方式: DLLDLL類型類型 入口函數(shù)入口函數(shù) 非非 MFC DLL MFC
31、 DLL 編程者提供編程者提供DllMainDllMain函數(shù)函數(shù) MFCMFC規(guī)則規(guī)則 DLL DLL CWinAppCWinApp對象的對象的InitInstance InitInstance 和和 ExitInstance ExitInstance MFCMFC擴展擴展 DLL DLL MFC DLLMFC DLL向?qū)上驅(qū)蒁llMain DllMain 函數(shù)函數(shù) 宏宏宏為宏為DLL和應(yīng)用程序的編寫提供了方便。像和應(yīng)用程序的編寫提供了方便。像AFX_EXT_CLASS、AFX_EXT_API、AFX_EXT_DATA在在DLL和應(yīng)用程序中將具有不同的定義,這取和應(yīng)用程序中將具有不同
32、的定義,這取決于決于_AFXEXT宏是否被定義。這使得在宏是否被定義。這使得在DLL和應(yīng)用程序中,使用統(tǒng)一的一個宏就可以表示和應(yīng)用程序中,使用統(tǒng)一的一個宏就可以表示出輸出和輸入的不同意思。出輸出和輸入的不同意思。在在DLL中,表示輸出因為中,表示輸出因為_AFXEXT被定義,被定義,通常是在編譯器的標識參數(shù)中指定通常是在編譯器的標識參數(shù)中指定/D_AFXEXT;在應(yīng)用程序中,那么表示輸入在應(yīng)用程序中,那么表示輸入_AFXEXT沒沒有定義。有定義。 AFX_CLASS_IMPORT _declspec(dllexport) AFX_API_IMPORT _declspec(dllexport)
33、AFX_DATA_IMPORT _declspec(dllexport) AFX_CLASS_EXPORT _declspec(dllexport) AFX_API_EXPORT _declspec(dllexport) AFX_DATA_EXPORT _declspec(dllexport) AFX_EXT_CLASS #ifdef _AFXEXT AFX_CLASS_EXPORT #else AFX_CLASS_IMPORT AFX_EXT_API #ifdef _AFXEXT AFX_API_EXPORT #else AFX_API_IMPORT AFX_EXT_DATA #ifdef
34、_AFXEXT AFX_DATA_EXPORT #else AFX_DATA_IMPORT class AFX_EXT_CLASS CExtDialog : public CDialog * #include .ExtDialog.h #pragma comment( lib, ExtDll.lib ) 而而“調(diào)用調(diào)用DLL按鈕的單擊事件的消息處置函數(shù)為:按鈕的單擊事件的消息處置函數(shù)為: void CLoadExtDllDlg:OnDllcallButton() CExtDialog extDialog; extDialog.DoModal(); Win32系統(tǒng)鉤子技術(shù)系統(tǒng)鉤子技術(shù)APIHOO
35、K技術(shù)應(yīng)用廣泛,常用于屏幕技術(shù)應(yīng)用廣泛,常用于屏幕取詞、網(wǎng)絡(luò)防火墻、病毒木馬、加殼軟取詞、網(wǎng)絡(luò)防火墻、病毒木馬、加殼軟件、串口紅外通信、游戲外掛、件、串口紅外通信、游戲外掛、Internet通信等領(lǐng)域。通信等領(lǐng)域。HOOK的中文意思就是鉤子,的中文意思就是鉤子,APIHOOK就是鉤住就是鉤住API,對,對API進展預(yù)進展預(yù)處置,先執(zhí)行我們的函數(shù)。處置,先執(zhí)行我們的函數(shù)。 APIHOOK技術(shù)技術(shù)鉤子的實質(zhì)是一段用以處置系統(tǒng)消息的程序,鉤子的實質(zhì)是一段用以處置系統(tǒng)消息的程序,通過系統(tǒng)調(diào)用,把它掛入系統(tǒng)。通過系統(tǒng)調(diào)用,把它掛入系統(tǒng)。鉤子的品種很多,每種鉤子可以截獲并處置相鉤子的品種很多,每種鉤子可以
36、截獲并處置相應(yīng)的消息,每當(dāng)特定的消息發(fā)出,在到達目的應(yīng)的消息,每當(dāng)特定的消息發(fā)出,在到達目的窗口之前,鉤子程序先行截獲該消息、得到對窗口之前,鉤子程序先行截獲該消息、得到對此消息的控制權(quán)。此時鉤子函數(shù)可以對截獲的此消息的控制權(quán)。此時鉤子函數(shù)可以對截獲的消息進展加工處置,甚至可以強迫完畢消息的消息進展加工處置,甚至可以強迫完畢消息的傳送。傳送。這有點類似與這有點類似與MFC中的中的PreTranslateMessage函數(shù),所不同的是該函數(shù)只能用于攔截本進程函數(shù),所不同的是該函數(shù)只能用于攔截本進程中的消息,而對系統(tǒng)消息那么無能為力。中的消息,而對系統(tǒng)消息那么無能為力。 Win32系統(tǒng)鉤子的實現(xiàn)系
37、統(tǒng)鉤子的實現(xiàn) 每品種型的鉤子均由系統(tǒng)來維護一個鉤每品種型的鉤子均由系統(tǒng)來維護一個鉤子鏈,最近裝置的鉤子位于鏈的開場,子鏈,最近裝置的鉤子位于鏈的開場,擁有最高的優(yōu)先級,而最先裝置的鉤子擁有最高的優(yōu)先級,而最先裝置的鉤子那么處在鏈的末尾。那么處在鏈的末尾。要實現(xiàn)要實現(xiàn)Win32的系統(tǒng)鉤子,首先要調(diào)用的系統(tǒng)鉤子,首先要調(diào)用SDK中的中的API函數(shù)函數(shù)SetWindowsHookEx來來裝置這個鉤子函數(shù),其原型是:裝置這個鉤子函數(shù),其原型是: HHOOK SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThrea
38、dId); 其中:其中: 第一個參數(shù)是鉤子的類型,常用的有第一個參數(shù)是鉤子的類型,常用的有WH_MOUSE、WH_KEYBOARD、WH_GETMESSAGE等;等; 第二個參數(shù)是鉤子函數(shù)的地址,當(dāng)鉤子鉤到任何消息后第二個參數(shù)是鉤子函數(shù)的地址,當(dāng)鉤子鉤到任何消息后便調(diào)用這個函數(shù);便調(diào)用這個函數(shù); 第三個參數(shù)是鉤子函數(shù)所在模塊的句柄;第三個參數(shù)是鉤子函數(shù)所在模塊的句柄; 第四個參數(shù)是鉤子相關(guān)函數(shù)的第四個參數(shù)是鉤子相關(guān)函數(shù)的ID用以指定想讓鉤子去鉤用以指定想讓鉤子去鉤哪個線程,為哪個線程,為0時那么攔截整個系統(tǒng)的消息此時為全局鉤時那么攔截整個系統(tǒng)的消息此時為全局鉤子。假如指定確定的線程,即為線程專
39、用鉤子。子。假如指定確定的線程,即為線程專用鉤子。 全局鉤子函數(shù)必需包含在全局鉤子函數(shù)必需包含在DLL動態(tài)鏈動態(tài)鏈接庫中,而線程專用鉤子那么可包含接庫中,而線程專用鉤子那么可包含在可執(zhí)行文件中。在可執(zhí)行文件中。得到控制權(quán)的鉤子函數(shù)在處置完消息后,得到控制權(quán)的鉤子函數(shù)在處置完消息后,可以調(diào)用另外一個可以調(diào)用另外一個SDK中的中的API函數(shù)函數(shù)CallNextHookEx來繼續(xù)傳送該消息。也來繼續(xù)傳送該消息。也可以通過直接返回可以通過直接返回TRUE來丟棄該消息,來丟棄該消息,阻止該消息的傳送。阻止該消息的傳送。使用全局鉤子函數(shù)時需要以使用全局鉤子函數(shù)時需要以DLL為載體,為載體,VC6中有三種形
40、式的中有三種形式的MFC DLL可供選擇,即規(guī)范可供選擇,即規(guī)范靜態(tài)鏈接靜態(tài)鏈接MFC DLL、規(guī)范動態(tài)鏈接、規(guī)范動態(tài)鏈接MFC DLL以及擴展以及擴展MFC DLL。第一種第一種DLL在編譯時把使用的在編譯時把使用的MFC代碼鏈接代碼鏈接到到DLL中,執(zhí)行程序時不需要其他中,執(zhí)行程序時不需要其他MFC動態(tài)動態(tài)鏈接類庫的支持,但體積較大;鏈接類庫的支持,但體積較大;第二種第二種DLL在運行時動態(tài)鏈接到在運行時動態(tài)鏈接到MFC類庫,類庫,因而體積較小,但卻依賴于因而體積較小,但卻依賴于MFC動態(tài)鏈接類庫動態(tài)鏈接類庫的支持;這兩種的支持;這兩種DLL均可被均可被MFC程序和程序和Win32程序使用
41、。程序使用。第三種第三種DLL的也是動態(tài)連接,但做為的也是動態(tài)連接,但做為MFC類類庫的擴展,只能被庫的擴展,只能被MFC程序使用。程序使用。 Win32 DLL BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved);其中:其中:第一個參數(shù)表示第一個參數(shù)表示DLL的實例句柄;的實例句柄;第三個參數(shù)系統(tǒng)保管;第三個參數(shù)系統(tǒng)保管;第二個參數(shù)指明了當(dāng)前調(diào)用該動態(tài)連接庫的狀態(tài),第二個參數(shù)指明了當(dāng)前調(diào)用該動態(tài)連接庫的狀態(tài),它有四個可能的值:它有四個可能的值:DLL_PROCESS_ATTACH進程載入、進程
42、載入、DLL_THREAD_ATTACH線程載入、線程載入、DLL_THREAD_DETACH線程卸載、線程卸載、DLL_PROCESS_DETACH進程卸載。進程卸載。DLL的共享問題的共享問題 由于在由于在Win32環(huán)境下,所有進程的空間都是互相獨立環(huán)境下,所有進程的空間都是互相獨立的,這減少了應(yīng)用程序間的互相影響,但大大增加了的,這減少了應(yīng)用程序間的互相影響,但大大增加了編程的難度。編程的難度。 當(dāng)進程在動態(tài)加載當(dāng)進程在動態(tài)加載DLL時,系統(tǒng)自動把時,系統(tǒng)自動把DLL地址映射地址映射到該進程的私有空間到該進程的私有空間; 而且也復(fù)制該而且也復(fù)制該DLL的全局數(shù)據(jù)的一份拷貝到該進程空的全局
43、數(shù)據(jù)的一份拷貝到該進程空間,每個進程所擁有的一樣的間,每個進程所擁有的一樣的DLL的全局數(shù)據(jù)其值卻的全局數(shù)據(jù)其值卻并不一定是一樣的。并不一定是一樣的。 當(dāng)當(dāng)DLL內(nèi)存被映射到進程空間中,每個進程都有自己內(nèi)存被映射到進程空間中,每個進程都有自己的全局內(nèi)存拷貝,加載的全局內(nèi)存拷貝,加載DLL的每一個新的進程都重新的每一個新的進程都重新初始化這一內(nèi)存區(qū)域,也就是說進程不能再共享初始化這一內(nèi)存區(qū)域,也就是說進程不能再共享DLL。全局共享數(shù)據(jù)的實現(xiàn)全局共享數(shù)據(jù)的實現(xiàn) 在在Win32環(huán)境下要想在多個進程中共享環(huán)境下要想在多個進程中共享數(shù)據(jù),就必需進展必要的設(shè)置。數(shù)據(jù),就必需進展必要的設(shè)置。一種方法便是把這
44、些需要共享的數(shù)據(jù)單一種方法便是把這些需要共享的數(shù)據(jù)單獨分別出來,放置在一個獨立的數(shù)據(jù)段獨分別出來,放置在一個獨立的數(shù)據(jù)段里,并把該段的屬性設(shè)置為共享,建立里,并把該段的屬性設(shè)置為共享,建立一個內(nèi)存共享的一個內(nèi)存共享的DLL。 #pragma data_seg用用#pragma data_seg建立一個新的數(shù)據(jù)段并定義建立一個新的數(shù)據(jù)段并定義共享數(shù)據(jù),其詳細格式為:共享數(shù)據(jù),其詳細格式為: #pragma data_seg shareddata) HWND sharedwnd=NULL;/共享數(shù)據(jù)共享數(shù)據(jù) #pragma data_seg() 所有在所有在data_seg pragmas語句之間聲明的變量都語句之間聲明的變量都將在將在shareddata段中。僅定義一個數(shù)據(jù)段還不能段中。僅定義一個數(shù)據(jù)段還不能到達共享數(shù)據(jù)的目的,還要告訴編譯器該段的屬到達共享數(shù)據(jù)的目的,還要告訴編譯器該段的屬性,有兩種方法可
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025《家庭居室裝飾裝修工程施工合同》(示范文本)
- 大學(xué)生參觀報告范文
- 上海視覺藝術(shù)學(xué)院《地圖制圖學(xué)B》2023-2024學(xué)年第一學(xué)期期末試卷
- 課題申報書:高等職業(yè)教育與區(qū)域創(chuàng)新能力發(fā)展的耦合路徑研究
- 課題申報書:高等教育擴張對就業(yè)匹配的影響機制與政策優(yōu)化研究
- 課題申報書:復(fù)雜口譯場景中伴語手勢影響源語理解的認知神經(jīng)機制研究
- 課題申報書:法國精英大學(xué)校拔尖創(chuàng)新人才培養(yǎng)特點與機制的實證研究
- 智能交通系統(tǒng)的設(shè)計與實現(xiàn)
- 8《夢游天姥吟留別》《登高》聯(lián)讀公開課一等獎創(chuàng)新教學(xué)設(shè)計(表格式)統(tǒng)編版高中語文必修上冊
- 40篇短文搞定高中英語3500單詞
- 智慧物業(yè)綜合管理系統(tǒng)
- 三年級語文上冊期末《句子》專項訓(xùn)練含答案
- 2024年中國遠洋海運集團招聘筆試參考題庫附帶答案詳解
- 2024年內(nèi)蒙古交通集團有限公司招聘筆試參考題庫附帶答案詳解
- 山東省聊城市文軒教育集團2023-2024學(xué)年九年級上學(xué)期期末化學(xué)模擬試卷
- 物業(yè)公司經(jīng)營規(guī)劃
- 2024年心腦血管藥物項目營銷策劃方案
- 攪拌站規(guī)劃設(shè)計方案
- 醫(yī)共體醫(yī)療質(zhì)量控制中心工作職責(zé)(終版改)
- 四川省綿陽市2023年九年級上學(xué)期期末化學(xué)試題附答案
評論
0/150
提交評論