?? 動態鏈接庫.txt
字號:
4.1 動態鏈接庫(DLL)的概述
4.1.1 DLL的定義 4.1.2 DLL的種類
4.1.3 動態鏈接庫和靜態鏈接庫的比較
4.2 DLL的基本理論
4.2.1 DLL入出口函數 4.2.2 DLL的鏈接方式
4.2.3 DLL動態鏈接庫庫函數的導出
4.2.4 從DLL中導出數據變量
4.3 用VC++開發環境生成DLL
4.3.1 用VC++生成WIN32 DLL
4.3.2 用VC++的MFC生成的 DLL
4.4 使用DLL
4.4.1 DLL的使用 4.4.2 DLL的調試
4.5 用VC++工具開發DLL的編程實例
4.1 動態鏈接庫(DLL)的概述
DLL特點:要求一個DEF文件;要求一個DllMain()的入口點,不是WinMain();DLL可以裝入,但不能執行.
4.1.1 DLL的定義
動態鏈接庫:是應用程序中的一段程序,將它放在一個不同的容器內,是一個可以從主.exe文件中單獨執行的模塊.可以認為一個DLL就是其它應用程序在執行時,能夠動態鏈接和調用的一組服務或函數.
DLL中存放的一般是一些公共的子程序段或各種資源和數據.一個最大的特點:可以實現應用程序本地化.如在DLL中封裝了各種語言,在安裝時進行適當的選擇就能實現本地化.
4.1.2 DLL的種類
主要有Win32 DLL和MFC APPWizard DLL兩大類及相關子類.
4.1.3 動態鏈接庫和靜態鏈接庫的比較
一個應用程序和函數的鏈接方式有兩種:
動態鏈接:在應用程序中不需要包含所要調用函數的代碼,而只需要所調DLL函數的一些信息,如DLL位置及相應的函數名.與函數的鏈接到編譯或運行時進行.
靜態鏈接:應用程序必須從靜態鏈接庫中取得所需調用函數的代碼,并把這些代碼放在應用程序的可執行代碼中.如一般的庫函數調用則屬此類.
DLL的特點:
有利于不同的應用程序共享數據和資源;
多個應用程序可以使用內存中的動態鏈接庫的單一映射,從而節約了程序運行和內存空間;
通過使用動態鏈接庫,應用程序可以拆分為相對獨立的功能模塊,有利于應用程序的升級;
當多個應用程序需要使用相同的函數時,通過使用動態鏈接庫,可以節約大量的硬盤空間.
4.2 DLL的基本理論
應用程序在使用DLL中的內容之前,系統要調用入出口函數完成DLL的初始化和終止工作.
4.2.1 DLL入出口函數
1,DllMain函數:在一個DLL的調用和撤除時被調用,一般發生在應用程序使用LoadLibrary 和FreeLibrary等函數及進程經線程啟動和終止時.函數結構為:
BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD fdwReason , LPVOID lpvReserved){
Switch (fdwReason){
Case DLL_PROCESS_ATTACH:break;/DLL映射到進程地址空間
Case DLL_THREAD_ATTACH:break;/一個線程被創建
Case DLL_THREAD_DETACH:break;/線程退出
Case DLL_PROCESS_DETACH:break;}/DLL從進程中解除映射
Return TRUE;}
其中hInstance是DLL的模塊句柄, lpvReserved 指定DLL初始化和清除的一些內容指針,fdwReason表明調用DllMain()函數的原因,具體如下:
在應用程序終止或顯式調用FreeLibrary()使DLL脫離進程的地址空間時發送
0
DLL_PROCESS_DETACH
在連接DLL的進程中一個線程終止時發送
3
DLL_THREAD_DETACH
在連接DLL的進程中生成一個新線程時發送
2
DLL_THREAD_ATTACH
當一個DLL首次裝入進程的地址空間時發送
1
DLL_PROCESS_ATTACH
含義
值
標志
2 . MFC的 Regular DLL 入出口
在MFC的DLL使用中,已編好了DllMain()函數,用戶不必寫,在裝載DLL時調用其成員函數InitInstance,在DLL退出時調用成員函數ExitInstance, 所需要的初始化和終止工作在這兩個函數中完成.
4.2.2 DLL的鏈接方式
DLL中包含一個或多個函數,調用這些函數的過程和編譯,鏈接的過程是獨立的.有兩種鏈接方式:隱式鏈接和顯式鏈接.
隱式鏈接DLL
原理:先說明DLL的導入庫文件(lib),因在庫文件中包含了一系列指向動態鏈接庫的指針.應用程序通過庫文件和DLL鏈接,調用DLL中的函數.
應用程序在調用DLL時需以下信息:
包含導出函數以及類聲明的頭文件,需要知道函數名和函數接口信息.
DLL的導入庫文件,應用程序在編譯鏈接需要.
實際的DLL文件,應用程序在運行時調用它.
顯式鏈接DLL
原理:應用程序在運行時通過函數調用來顯式裝載和卸載DLL,并通過函數指針來調用DLL的導出函數,這種方式主要用于靈活控制DLL庫動態裝入和裝出的場合.
使用:第一步調用函數LoadLibrary或AfxLoadLibrary裝載DLL并得到模塊句柄.原型如下:
HINSTANCE LoadLibrary(LPCSTR lpLibFileName);
參數為要裝入的DLL的文件名字.當此函數被多次調用時,在進程中只有一份DLL程序和數據,系統通過計數器來標識.
第二步:調用函數GetProcAddress來獲得導出函數的指針.函數原型如下:
FARPROC GetProcAddress(HMODULE hModul,LPCSTR lpProName);
hMoudul是DLL的實例句柄,參數lpProName是相應的函數名.
第三步:在使用完后調用函數FreeLibrary或AfxFreeLibrary 來釋放DLL. FreeLibrary原型為
BOOL FreeLibrary(HINSTANCE hInstLib);
參數是裝入的DLL模塊的句柄,調用一次,DLL計數器值減一,最終回到0,系統釋放被DLL占用的空間.
4.2.3 DLL動態鏈接庫庫函數的導出
動態鏈接庫中的函數可以分為導出函數和內部函數.
動態鏈接庫中的函數主要有以下幾種:
(1)在源程序中使用關鍵字:_declspec(dllexport).
此函數可從一個DLL中輸出數據,函數,類,類成員函數而不需要DEF文件.
原理:根據一個指定的存儲類屬性(extended-attribute)存儲某個項數據.其屬性主要有:allocate("segname"),
dllimport,dllexport,naked等,語法如下:
_declspec(extended_attribute) declarator;具體使用有二種情況:_declspec(dllexport) void_cdecl Function1(void);
Class _declspec(dllexport) CExportCLass:public Cobject
{……..}
(2) 在DEF文件中通過EXPORTS來聲明函數
DEF是由一個或多個描述DLL屬性的語句組成的文本文件,主要有:
LIBRARY語句:用于指定DLL的內部名;
DESCRIPTION語句:用于描述DLL特性;
SECTIONS語句:用于設置段的屬性,這些屬性有:
READ,WRITE,EXECUTE,SHARED;
EXPORTS語句:用于列出被導出的函數名及相關信息;
VERSION語句:該DLL的版本號.
例:
LIBRARY "Dll"
DESCRIPTION 'Dll Windows Dynamic Link Library'
EXPORTS
Function1 @1
Function2 @2
Function3 @3
EXPORTS ……….
……….
庫函數的聲明如下:
Entryname[=internalname] [@ordinal[NONAME]]
外部名 內部名 序號 不輸出函數名
4.2.4 從DLL中導出數據變量
(1)使用DEF文件,設置關鍵字CONSTANT導出.通過用CONSTANT標志時,表明前面導出的不是函數,而是一個數據變量.
EXPORTS
Bvariable @4 CONSTANT
Extern BOOL bVariable ;//程序中的應用
(2)可以在應用程序中使用關鍵字 _declspec(dllimport)
引入對DLL導出的變量的作用,在DLL源程序中以_declspec(dllexport)來說明要導出的變量.
4.3 用VC++開發環境生成DLL
4.3.1 用VC++生成WIN32 DLL
Win 32的DLL自動生成過程:
FILE->NEW->PROJECT->Win32 Dynamic-Link Library->ok,然后選擇相應的類型工程.
2. DLL工程類型:
(1)空DLL工程
在需要時編寫程序源文件,和DEF文件
(2)簡單的DLL工程
只有DllMain(),沒有導出和其它變量或函數,不生成DEF文件,編譯后也不產生LIB文件.
(3)導出變量,函數和類的DLL
較為詳細地建立了DLL中的一些基本成分,包括導出關鍵字_declspec(dllexport),生成LIB文件.
4.3.2 用VC++的MFC生成的 DLL
MFC類庫的DLL自動生成過程:
FILE->NEW->PROJECT->MFC AppWizard(dll) -> ok,然后選擇相應的類型工程.
2. MFC AppWizard DLL類型:
(1)靜態鏈接MFC的 Regular DLL
在內部使用MFC的DLL庫,可被MFC和非MFC的應用程序使用,若在工程建立時使用的是MFC靜態庫,導出函數使用標準C語言接口,創建時自動生成DEF文件,如導出函數:MyExportFunction()用:
extern "c" EXPORT MyExportFunction();
(2)動態鏈接MFC 的Regular DLL
動態鏈接MFC 的Regular DLL和靜態鏈接MFC 的Regular DLL基本相似,最后都是由CWinApp派生類的成員函數InitInstance和ExitInstance來完成DLL的初始化和應用程序調用結束時的終止,清理工作.
不同的是:DLL在建立時用的是MFC的動態共享庫.其導出函數的開頭部分使用AFX_MANAGE_STATE宏.
(3)動態鏈接MFC 的擴展 DLL
MFC 的擴展(Extension) DLL是從已有的MFC類派生新類的DLL,它建立時作用MFC動態鏈接庫,它的導出函數只能由使用MFC動態共享庫的MFC應用程序調用.
注:如果顯示鏈接到這種DLL的應用程序是多線程的,則應使用AfxLoadLibrary 和AfxfreeLibray來裝載和卸載擴展DLL,而不要用AfxLoadLibrary 和AfxfreeLibray.
4.4 使用DLL
4.4.1 DLL的使用
調用DLL的應用程序在沒有指定DLL位置時,默認位置如下:
(1)含有該應用程序的目錄
(2)當前執行所在目錄
(3)Windows的系統目錄,如system目錄
(4)Windows目錄
(5)在環境變量PATH中列出的目錄
4.4.2 DLL的調試
(1)使用應用程序調試DLL
打開應用程序的工程, 選擇Project->settings-> debug-> category->additional DLLs->指定調試的DLL文件.
(2)使用DLL的工程調試DLL
打開DLL工程, 選擇Project->settings-> debug -> category->additional DLLs->指定調試的DLL文件.
此時可以設置斷點進行調試.
(3)同時使用應用程序和DLL調試DLL
可以在同一個工作區中打開應用程序工程和DLL工程,如下:
選擇Project->Insert Project into Workspace-> Win32 debug 進行DLL程序調試.
4.5 用VC++工具開發DLL的編程實例
(見P93-P102)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -