1. 程式人生 > >DLL函式封裝及呼叫例項

DLL函式封裝及呼叫例項

動態呼叫的意思是顯式呼叫,是由使用者自己選擇呼叫哪個DLL檔案,在windows系統中,與動態連結庫呼叫相關的函式主要有3個:

1.LoadLibrary,顧名思義,該函式的作用是載入DLL檔案,因此該函式的引數就是你想要使用的DLL檔案;

2.GetProcAddress,大概意思是獲得欲使用函式的地址,其有兩個引數,一個是後面會提到的控制代碼,另外一個就是DLL中的函式;

3.FreeLibrary,釋放動態連結庫。

下面通過一個例項來演示如何定義並顯式呼叫DLL中的函式。

建立生成自己的dll檔案

簡單起見,我們dll中只包含一個函式,這個函式我們起名叫做multiply,作用就是實現兩個數的相乘。我們新建一個專案multiplydll如下圖

點選確定,下一步,選擇DLL,完成,如下圖
得到如下圖所示結果,注意在原始檔部分會自動生成multiplydll.cpp檔案,我們將在裡面新增我們的乘函式
新增乘函式,編譯成功如下圖
此時我們去專案目錄下F:\src\multiplydll\Debug會看到一個生成的dll檔案如下:

測試呼叫我們生成的DLL檔案中的函式

現在我們新建立一個專案,來測試呼叫我們生成的dll。我們新建一個專案multi_test,確定,下一步,空專案,見下面兩圖

新增原始檔test做簡單的測試
簡單起見,我們將生成的dll檔案複製到當前專案下,如下圖
注意在新建的測試專案中需要做一點更改如下圖

測試程式碼如下:
#include<iostream>
#include<Windows.h>//這個標頭檔案非常重要,必須加上!
using namespace std;
typedef int(*dllfunc)(int a, int b);//這裡的dllfun形式上和我們生成的DLL檔案中的函式一致,我們的dll中定義的函式有兩個整型引數,因此這裡也是int a,int b
int main()
{
	HINSTANCE hdll;//定義一個控制代碼例項,來獲取dll的例項地址
	//這裡為簡單起見,我們直接將生成的multiply.dll檔案複製到當前專案下,否則下面一句你需要替換成dll的地址
	hdll = LoadLibrary("multiplydll.dll");//載入生成的dll檔案,因為我們把生成的dll檔案複製到當前專案目錄下了,所以直接寫就行了
	//下面判斷當前dll是否載入成功
	if (hdll == NULL)
	{
		cout << "DLL載入失敗" << endl;
		return 0;
	}
	//如果通過上面則表明載入成功了,下面我們需要取出dll裡面函式的地址
	dllfunc add_obj = (dllfunc)GetProcAddress(hdll, "multiply");//此處兩個引數一個是我們的控制代碼,另外一個是dll中函式名,取出來給add_obj
	//同樣,取址是否成功呢?判斷一下!
	if (add_obj == NULL)
	{
		cout << "獲取DLL中函式地址失敗!" << endl;
		return 0;
	}
	//獲取函式地址成功後,我們就可以使用dll中的函數了
	cout << add_obj(3, 5) << endl;
        FreeLibrary(hdll);
	return 0;
}
結果
注意:上面的DLL中僅僅包含一個函式,那如果我想實現多個函式的封裝呼叫該怎麼辦呢?一個可行但麻煩的方法是對每一個函式單獨建一個dll,然後分別載入每個dll再呼叫每個函式,顯然這是非常麻煩的。這個“問題”也困擾了我兩天,但是突然注意到,在載入完dll之後我們獲取的是dll函式中的地址啊!引數是函式名而不是dll的名字!因此,只需要一個dll就可以。其餘步驟類似,下面給出一個求面積的例項,分別求矩形面積和圓形面積,程式碼及執行結果如下:
#include<iostream>
#include<Windows.h>
using namespace std;
typedef double(*dllfun1)(double l, double d);
typedef double(*dllfun2)(double r);
int main()
{
	double width, length;
	cout << "please enter the width and length of a rectangle:" << endl;
	cin >> width >> length;
	HINSTANCE hdll;
	hdll = LoadLibrary("myArea.dll");
	if (hdll == NULL)
	{
		cout << "DLL載入失敗" << endl;
		return 0;
	}
	dllfun1 re = (dllfun1)GetProcAddress(hdll, "rect");
	if (re == NULL)
	{
		cout << "獲取DLL函式地址失敗" << endl;
		return 0;
	}
	cout << "Area of the rectangle is:" << re(length, width) << endl;
	double radius;
	cout << "please enter the radius of a circle:" << endl;
	cin >> radius;
	dllfun2 ci = (dllfun2)GetProcAddress(hdll, "circle");
	if (ci == NULL)
	{
		cout << "獲取DLL函式地址失敗" << endl;
		return 0;
	}
	cout << "Area of the circle is:" << ci(radius) << endl;
	FreeLibrary(hdll);
	return 0;
}

參考:http://blog.csdn.net/very_2/article/details/6534915             http://blog.csdn.net/ojshilu/article/details/12954957