vs環境下C++dll生成和使用(基礎篇)
阿新 • • 發佈:2018-11-20
動態庫和靜態庫:
動態庫:全名動態連結庫,用於將你的函式封裝,讓別人只能呼叫,不能看你的實現程式碼。由引入庫和dll組成:引入庫包含匯出的函式和變數名,dll包含實際的函式和資料,執行時載入訪問dll檔案。
Windows API中的所有函式都封裝在dll裡面,最重要的三個:
- Kernel32.dll:包含管理記憶體、程序和執行緒的各個函式。
- User32.dll:包含用於執行使用者介面任務,如視窗和訊息機制。
-
GDI32.dll:包含用於畫圖和顯示文字的各個函式。
靜態庫:函式和資料被編譯進一個二進位制檔案(lib),編譯時,連結器會複製並和其他模組組合,形成可執行檔案。適合小型程式,不然可執行檔案太大,而且每次修改都要重新編譯。
動態庫的好處:
- 可以用多種語言編寫,適合跨平臺。
- 提供二次開發平臺,封裝好底層庫,由二次開發衍生出多種產品。
- 節約磁碟空間和記憶體。同時執行多個程式,可以呼叫一個dll。
生成動態庫:
先說win32封裝函式:
1.新建win32控制檯空專案。
2.新增dllMain.cpp,加入dll的主函式:
我也是百度的,具體變數什麼意思再查吧,反正每個都要有這個主函式。
#include <Windows.h> BOOL WINAPI DllMain( HINSTANCE hinstDLL, // handle to DLL module DWORD fdwReason, // reason for calling function LPVOID lpReserved ) // reserved { // Perform actions based on the reason for calling. switch( fdwReason ) { case DLL_PROCESS_ATTACH: // Initialize once for each new process. // Return FALSE to fail DLL load. break; case DLL_THREAD_ATTACH: // Do thread-specific initialization. break; case DLL_THREAD_DETACH: // Do thread-specific cleanup. break; case DLL_PROCESS_DETACH: // Perform any necessary cleanup. break; } return TRUE; // Successful DLL_PROCESS_ATTACH. }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
3.新增宣告檔案MyDll.h
//每個函式前面都需要加,C和C++看你具體的編譯環境,一般選C比較通用。 extern "C" _declspec(dllexport) int Sum(int a,int b); extern "C++" _declspec(dllexport) int Sum2(int a,int b); ///////////////////也可以///////////////// #ifndef MYDll_H_ #define MYDll_H_ #ifdef MYDLL #define MYDLL extern "C" _declspec(dllimport) #else #define MYDLL extern "C" _declspec(dllexport) #endif MYDLL int Sum(int a,int b); #endif //#ifndef MYDll_H_
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
最後編譯就生成了dll和lib。注意,並不能執行,這只是個連結庫。
dll的呼叫:
使用dll前首先要只要裡面有啥,要麼將宣告檔案一起給,要麼寫好文件,要麼用工具查。系統cmd和vs的bin目錄下都可以查,具體用法自行百度吧。
呼叫的方法有兩種,隱式和顯示。
隱式需要.h,.lib,.dll三件套,然後:
專案->屬性->配置屬性->VC++ 目錄-> 在“包含目錄”裡新增標頭檔案xxxdll.h所在的目錄
專案->屬性->配置屬性->VC++ 目錄-> 在“庫目錄”裡新增標頭檔案xxx.lib所在的目錄
專案->屬性->配置屬性->連結器->輸入-> 在“附加依賴項”裡新增“xxx.lib”(若有多個 lib 則以空格隔開)
最後需要呼叫的時候包含對應dll.h標頭檔案就好了,很方便。和呼叫本地方法一樣。
還有一種隱式呼叫:
#pragma comment(lib,"cdll.lib") //路徑注意要對
extern "C" _declspec(dllimport) int addfun(int a,int b);//等於包含標頭檔案
- 1
- 2
顯示呼叫:適合少量呼叫。
typedef double (*pAdd)(double a, double b);
typedef double (*pSubtract)(double a, double b);
HMODULE hDLL = LoadLibrary("testdll.dll"); //載入dll檔案
if(hDLL != NULL)
{
pAdd fp1 = pAdd(GetProcAddress(hDLL, MAKEINTRESOURCE(1))); //得到dll中的第一個函式
if(fp1 != NULL)
{
cout<<fp1(2.5, 5.5)<<endl;
}
else
{
cout<<"Cannot Find Function "<<"add"<<endl;
}
pAdd addfun = (pAdd)GetProcAddress(hDLL, TEXT("addfun"));//直接使用原工程函式名
FreeLibrary(hDLL);
}
else
{
std::cout<<"Cannot Find "<<"testdll"<<std::endl;
}