1. 程式人生 > >C++對dll連結庫的顯示(動態)呼叫和隱式(靜態)呼叫

C++對dll連結庫的顯示(動態)呼叫和隱式(靜態)呼叫

C++呼叫dll連結庫的方式有兩種:動態呼叫(又叫顯示呼叫)、靜態呼叫(又叫隱式呼叫)。

一、靜態呼叫dll

    靜態呼叫,又稱隱式呼叫。由編譯系統完成對DLL的載入和應用程式結束時DLL解除安裝的編碼,Windows作業系統會負責控制DLL匯入記憶體的次數。這種呼叫方式簡單,能夠滿足通常的要求。通常採用的方法是把產生動態連線庫時產生的.LIB檔案(函式入口位置檔案)加入到應用程式的工程中,想使用DLL中的函式時,只須在原始檔中宣告一下。 

LIB檔案包含了每一個DLL匯出函式的符號名和可選擇的標識號以及DLL檔名,不含有實際的程式碼。Lib檔案包含的資訊進入到生成的應用程式中,被呼叫的DLL檔案會在應用程式載入時同時載入在到記憶體中。 

具體方法:

1、在使用連結庫的程式碼開頭加入,第二行是要呼叫的連結庫裡的函式:

#pragma comment(lib,"mydll.lib")  

extern "C" __declspec(dllimport)  int hello(int); 

2、將要呼叫的連結庫的lib放入專案原始碼中,然後編譯。(編譯的時候不需要dll。這裡把靜態部分lib編譯進了exe,但動態庫dll還沒用。)

3、執行之前要把dll放到exe目錄下。

二、動態呼叫dll

    動態呼叫,即顯式呼叫,是由程式設計者用API函式載入和解除安裝DLL來達到呼叫DLL的目的,比較複雜,但能更加有效地使用記憶體。在Windows系統中,與動態庫呼叫有關的函式包括: 
①LoadLibrary(或MFC 的AfxLoadLibrary),裝載動態庫。 
②GetProcAddress,獲取要引入的函式,將符號名或標識號轉換為DLL內部地址。 
③FreeLibrary(或MFC的AfxFreeLibrary),釋放動態連結庫。

具體方法:
1.宣告標頭檔案<windows.h>。

2.然後用typedef定義一個指標函式型別,typedef  int(*fun)(int) 。這個指標型別,要和你呼叫的函式型別和引數保持一致。

3.定義一個控制代碼例項,用來取DLL的例項地址。HINSTANCE hdll。
格式為hdll=LoadLibrary(“DLL地址”);這裡字串型別是LPSTR,當是unicode字符集的時候會不行,因此要在配置-屬性-常規裡面把預設字符集“unicode”改成支援多字元擴充套件即可。4.取的地址要判斷,返回的控制代碼是否為空,如果為無效控制代碼,那麼要釋放載入DLL所佔用的記憶體。

FreeLibrary(hdll);5.然後定義一個函式指標,用來獲取你要用的函式地址。先是定義一個函式指標 fun FUN;然後通過GetProcAdress來獲取函式的地址,引數是DLL的控制代碼和你要呼叫的函式名:比如:FUN=(fun)GetProcAdress(hdll,"hello")。這裡也要判斷要函式指標是否為空,如果沒取到要求的函式,那麼要釋放控制代碼。
6.然後通過函式指標來呼叫函式。FUN(int count);這裡不能用函式名來使用函式,因為這個DLL本身不是當前CPP的一部分,而是通過windows去呼叫.沒有在這個工程裡宣告或者定義,而是暴露出一個頭,要指標獲取他的地址,通過指標來呼叫。

程式碼:

#include <stdio.h>
#include <Windows.h>

typedef int(*dllfun)(int);  //定義形式對應的函式指標型別

int main()
{
	int a = 2;
	dllfun lucky; //宣告一個函式指標

	HINSTANCE hdll;
	hdll = LoadLibrary("mydll.dll");
	if(hdll == NULL)
	{
		printf("無法載入dll\n");
		FreeLibrary(hdll);
		getchar();
		return 0;
	}
	lucky = (dllfun)GetProcAddress(hdll,"lucky"); 
	if(lucky == NULL)
	{
		printf("無法獲取函式地址\n");
		FreeLibrary(hdll);
		getchar();
		return 0;
	}

	int b = lucky(a);
	printf("%d\n",b);

	FreeLibrary(hdll);
	getchar();
	return 1;
}