1. 程式人生 > 實用技巧 >VS2008 C++ 呼叫一個簡單的DLL檔案

VS2008 C++ 呼叫一個簡單的DLL檔案

上一期我們說到如何用VS2008 C++生成一個簡單的DLL檔案,這次我們來試著去呼叫它。

C++呼叫DLL檔案的方法也是有兩種,分為顯示呼叫與隱式呼叫,也稱為動態呼叫與靜態呼叫。

靜態呼叫是通過連結器將DLL函式的匯出寫進可執行檔案中,而動態呼叫不是連結時完成的,是在執行時完成的,動態呼叫不會在可執行檔案中寫入DLL相關的資訊。

大家可以根據實際專案的需求來選擇哪種呼叫方法。

接下來介紹如何呼叫DLL的內容,部分需要參考上一篇文章的內容。

連結:https://www.cnblogs.com/cokefan/p/13302971.html

方法1.隱式呼叫(靜態呼叫)

1.首先需要準備三個檔案,生成DLL時的.h標頭檔案、.lib靜態庫檔案和.dll動態庫檔案。這裡我們使用上期生成的MyDLL.h、MyDLL.lib和MyDLL.dll,在後面可以複製到專案資料夾下。

2.新建一個型別為控制檯應用程式的空專案,命名為DLLTest,具體建立專案的方法可以參考我的上一篇文章。這裡就不再詳細介紹了。

3.建立好專案之後,在選單欄選擇專案->屬性(ALT+F7)。這裡進行兩項屬性配置:

​ 3.1 屬性頁->配置屬性->連結器->常規->附加庫目錄,點選附加庫目錄右側的...,如圖在彈出的視窗選擇插入新行按鈕,單擊...,選擇你放MyDLL.lib檔案的目錄。這裡我就放在了專案資料夾下面,所以目錄就是"C:\Users\Fan\Desktop\DLLTest\DLLTest",最後單擊確定按鈕,這一步完成。

​ 3.2 屬性頁->配置屬性->連結器->常規->附加依賴項,點選附加依賴項右側的...,在彈出的視窗中輸入MyDLL.lib,如圖所示,最後單擊確定,再點選屬性頁的確定,配置就完成了。

再簡單解釋一下:附加庫目錄是指向你的lib目錄,附加依賴項是新增庫目錄中.lib檔案的名稱。

4.將MyDLL.h檔案複製到你的專案資料夾下,在VS2008中的解決方案資源管理器中選擇標頭檔案,單擊右鍵,新增->現有項,選擇MyDLL.h。

5.在原始檔中新增一個名為main.cpp新建項,並複製以下程式碼到檔案中。

#include <iostream>
#include "MyDLL.h"

int main()
{
	std::cout << "add(3,4):" << add(3,4) << std::endl;
	std::cout << "sub(9,2):" << sub(9,2) << std::endl;
	return 0;
}

6.在選單中選擇除錯->開始執行(不除錯) 來執行我們的專案,如圖所示。

方法2.顯式呼叫(動態呼叫)

1.首先我們需要只需準備一個檔案,即MyDLL.dll,在後面可以複製到專案資料夾下。

2.新建一個型別為控制檯應用程式的空專案,命名為DLLTest。

3.在原始檔中新增一個名為main.cpp新建項,並複製以下程式碼到檔案中。

#include <iostream>
#include <windows.h>

typedef int(*func)(int, int);

int main()
{
	LPCWSTR dllName = L"MyDLL.dll";
	const char* funName = "add";

	HMODULE hDLL = LoadLibrary(dllName);//通過dll名稱載入dll,將dll放在該工程根路徑即可
	if(hDLL != NULL)
	{
		func func_add = func(GetProcAddress(hDLL, funName));//獲取匯入到應用程式中的函式指標,根據函式名取得 
		//func func_add = func(GetProcAddress(hDLL, MAKEINTRESOURCE(1)));//根據直接使用DLL中函數出現的順序號,可以通過Depends軟體瞭解,也是在.def檔案中定義的順序
		if(func_add != NULL)
			std::cout << "func_add(3,4):" << func_add(3, 4) << std::endl;
		else
		{
			std::cout << "Cannot Find Function : " << funName << std::endl;
		}
		FreeLibrary(hDLL);//使用完需要釋放
	}
	else
	{
		std::wcout << "Cannot Find dll : " << dllName << std::endl;
	}

	return 0;
}

4.執行專案,在選單欄中選擇除錯->開始執行(不除錯)。執行結果如圖。

簡單的解釋:

typedef int(*func)(int, int);

這裡我們定義一個指向與DLL中所需函式型別相同的原型指標。

例如DLL中的 int add(int, int); 在宣告中引數名可省略,但是引數型別不可省略。

關於dllName的型別LPCWSTR,它的定義是typedef const wchar_t* LPCWSTR;

LPCWSTR是一個指向unicode編碼字串的32位指標,所指向字串是wchar型,而不是char型。

所以在第8行定義字串的前面要加L,第26行輸出時需要使用std::wcout,這也是輸出寬字元專用的。

如果希望以上程式碼可以使用const char*型來輸出,可以更改配置,具體操作如下:

選單欄->專案->屬性->配置屬性->常規->字符集,本身是使用Unicode字符集,更改為使用多位元組字符集,即可。

上述程式碼的第8行和第26行分別改為,

	const char* dllName = "MyDLL.dll";
	std::cout << "Cannot Find dll : " << dllName << std::endl;

程式也可以正常運行了,在實際使用中可以根據實際專案需求進行選擇。


參考資料:

[1]VS2008 C++生成一個簡單的DLL檔案

https://www.cnblogs.com/cokefan/p/13302971.html