DLL

DLL的載入大致上分兩種

1 、 隱式連結(Implicitly Link)(也叫載入期動態連結 Load-Time Dynamic Linking)



這種是屬於靜態載入,就是指,程式編譯時會預留函式的空間。所以當程式被Windows的loader載入到記憶體中後,loader會自動檢查執行檔中所有的import function的定義,把所有需要的DLLs都載入到記憶體裡面。

優點:

1、 使用DLL裡面的Function的方法,就像是包含在自己程式裡面的function一樣可以使用。


2 、 動作較為簡單,載入的方法跟尋找DLL的動作由作業系統負責處理,應用程式不用調整也無法去干涉。


缺點:

1 、 當找不到DLL時,程式就不能開啟(就是常見的找不到xxx.dll)。

2 、 編譯時需要先include DLL的宣告檔(通常是.h)。

3 、 隨著載入的DLLs增加,載入應用程式的速度會便慢。

4 、 若遇到不同品牌 的C++編譯器時靜態載入可就沒有這麼簡單處理了,因為當函式經過Calling Conventions的處理後,若要使用其他品牌編譯器所致造出的DLL須得大動干戈才行。


2 、 顯式連結(Explicit Linking)



跟他的名字一樣,就是在程式執行的過程中動態載入DLL,用完了就馬上釋放DLL

優點:

1 、DLL只要需要時才會載入到記憶體中,可以更有效的使用記憶體。

2 、 應用程式開始的時候不用先載入DLL,所以載入速度比上面的方法快。

3 、 編譯時不須額外include DLL函式的宣告檔。

4 、 讓我們可以更清楚DLL的載入流程。

缺點:

要多花一些程式碼來處理載入的過程!


下面是test.cpp,他會產生一個test.dll


1. #include

2. #include

3. using namespace std;

4.

5. __declspec( dllexport ) int AddFunction(int a, int b)

6. { return a+b; }

7. __declspec( dllexport ) int SubFunction(int a, int b)

8. { return a-b; }

9.

10. // 進入點

11. BOOL APIENTRY DllMain( HANDLE hModule,

12. DWORD ul_reason_for_call,

13. LPVOID lpReserved)

14. {

15. return TRUE;

16. }


接下來要教如何在程式過程中載入DLL,只有三個步驟,那就稱它為動態載入三步驟:

1.使用LoadLibrary()函式載入DLL

2.使用GetProcessAddress() 函式取得所要使用的函式的位址

3.不需要用到此DLL時,呼叫FreeLibrary()函式將DLL釋放


先把使用的程式寫出來




1. #include

2. int WINAPI

3. WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,

4. LPSTR lpCmdLine, int iCmdShow){

5.

6. HINSTANCE hTest;

7. HMODULE myPlugin=NULL;

8. myPlugin = LoadLibrary( " test.dll " )

9. //宣告function

10. typedef int (*PFNAddFunction)( int a , int b);

11. PFNAddFunction pfnAdd = (PFNAddFunction)GetProcAddress( myPlugin, "?AddFunction@@YAHHH@Z" );

12. //宣告function

13. typedef int (*PFNSubFunction)( int a , int b);

14. PFNSubFunction pfnSub = (PFNSubFunction)GetProcAddress( myPlugin, "?SubFunction@@YAHHH@Z" );

15.

16. int ans;

17. ans = pfnSub(5,3); //ans會是2

18. ans = pfnAdd(6,4); //ans會是10

19.

20. FreeLibrary(hTest);

21. return 0;

22. }


最有疑問的是GetProcAddress裡面的 ?AddFunction@@YAHHH@Z 是怎麼出來的??

那是我用VS2005編譯出來的函式名稱,當我們編譯成DLL後可以用VC6有附的一個工具,叫做Dependency Walker 來看編譯出來的address。


其他內容就應該是很簡單的了。


內容轉載自 維尼的蜂巢

0 意見: