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檔案