1. 程式人生 > >vs環境下C++dll生成和使用(基礎篇)

vs環境下C++dll生成和使用(基礎篇)

動態庫和靜態庫:

動態庫:全名動態連結庫,用於將你的函式封裝,讓別人只能呼叫,不能看你的實現程式碼。由引入庫和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; 
}