Visual Studio 2017 動態連結庫(.dll)生成與使用的簡明教學

2020-10-21 12:00:30
  • 寫在前面

動態連結庫(Dynamic Link Library 或者 Dynamic-link Library,縮寫為 DLL),是微軟公司在微軟Windows作業系統中,實現共用函數庫概念的一種方式。這些庫函數的擴充套件名是 」.dll"、".ocx"(包含ActiveX控制的庫)或者 ".drv"(舊式的系統驅動程式)。本篇文章要介紹的是擴充套件名為".dll"的動態連結庫。

動態連結提供了一種方法,使程序可以呼叫不屬於其可執行程式碼的函數。函數的可執行程式碼位於一個 DLL檔案中,該DLL包含一個或多個已被編譯、連結並與使用它們的程序分開儲存的函數。DLL還有助於共用資料和資源。多個應用程式可同時存取記憶體中單個 DLL 副本的內容。

使用動態連結庫可以更為容易地將更新應用於各個模組,而不會影響該程式的其他部分。例如,您有一個大型網路遊戲,如果把整個數百MB甚至數GB的遊戲的程式碼都放在一個應用程式裡,日後的修改工作將會十分費時,而如果把不同功能的程式碼分別放在數個動態連結庫中,您無需重新生成或安裝整個程式就可以應用更新。

  • dll的建立

1、開啟"Visual Studio",新建專案-->Visual C++-->Windows桌面-->動態連結庫(DLL)。這裡我們取專案名為Dll1。

2、建立成功後,按照模板,應該會有下圖所示的檔案。

然後建立屬於自己的.cpp檔案和.h檔案,右鍵資源管理器裡的"原始檔"和"標頭檔案",選擇"新建項..."。

3、在.cpp中寫下一個簡單的函數。

#include "pch.h"    //必要的標頭檔案
#include "myDll1.h" //自己的標頭檔案

//一個簡單的函數
int myAdd(int a, int b)
{
    return a + b;
}

4、在.h中寫下宣告。

#pragma once  //規定只編譯一次

//宏定義,增加可讀性
#define DATAEXCHANGEDLL_API __declspec(dllexport)

//按C進行編譯,宣告.cpp中的函數
extern "C" DATAEXCHANGEDLL_API int myAdd(int a, int b);

5、選擇x64後,點選選單欄中的"生成"-->"重新生成解決方案"

成功。

6、生成的.dll,.lib均在專案根目錄的x64/Debug資料夾裡


  • dll的使用

1、開啟"Visual Studio",新建專案-->Visual C++-->控制檯應用。這裡我們取專案名為Dll1_test。

2、將之前專案的三個檔案移植到新的專案資料夾內。

然後在Visual Studio內進行新增。

右鍵資源管理器的"標頭檔案",新增"現有項...",選擇"myDll1.h"。

右鍵資源管理器的"資原始檔",新增"現有項...",選擇"Dll1.lib"。效果如下圖

3、在要使用到動態連結庫的.cpp檔案中,參照標頭檔案"myDll.h",就可以使用Dll1.dll裡面的函數了。

#include <iostream>
#include "myDll1.h"
using namespace std;
int main()
{
    int c = myAdd(1, 2);
    cout << c << endl;
    system("pause");
    return 0;
}

成功。


  • 實戰

1、建立dll專案同上,名字取為"A1_<學號>",同理新增自己的.cpp和.h,名字均為"A1_<學號>.<xxx>",在.cpp內寫函數,在.h中寫宣告。

.cpp:

#include "pch.h"
#include "A1_000000.h"
#include <iostream>

using namespace std;

/**
 * 求rawIntData每個元素的和
 * @rawIntData 資料陣列
 * @rawIntData 資料長度
 * @result 結果
 * @return {返回值型別} 返回值說明
 */
int NewIntAdd(int rawIntData[], int dataNum, int &result)
{
    result = 0;
    for (size_t i = 0; i < dataNum; i++)
    {
        result += rawIntData[i];
    }
    return 0;
}
/**
 * 求rawIntData每個元素的和
 * @rawIntData 資料陣列
 * @rawIntData 資料長度
 * @result 結果
 * @return {返回值型別} 返回值說明
 */
int NewFloatAdd(float rawFloatData[], int dataNum, float& result)
{
    result = 0.0f;
    for (size_t i = 0; i < dataNum; i++)
    {
        result += rawFloatData[i];
    }
    return 0;
}
/**
 * 求rawIntData 求最大值
 * @rawIntData 資料陣列
 * @rawIntData 資料長度
 * @result 結果
 * @return {返回值型別} 返回值說明
 */
int NewFloatMAX(float rawFloatData[], int dataNum, float& result)
{
    return 0;
}

.h:

#pragma once

#define DATAEXCHANGEDLL_API __declspec(dllexport)
// ***上面為固定的宏定義格式***


// ***下面加入自己的函數宣告***
extern "C"
{
    DATAEXCHANGEDLL_API int NewIntAdd(int rawIntData[], int dataNum, int &result);
    DATAEXCHANGEDLL_API int NewFloatAdd(float rawFloatData[], int dataNum, float& result);
    DATAEXCHANGEDLL_API int NewFloatMAX(float rawFloatData[], int dataNum, float& result);
}

2、同樣的,選擇x64,點選"重新生成解決方案",就可以生成相應的檔案,位置跟前面的一樣。

3、將三個檔案分別移植到"Assignment1"專案中,然後按步驟新增檔案進入資源管理器。

將原有的三個函數程式碼刪掉或註釋,然後執行即可出結果。

成功。

p.s.在.cpp中,選中NewIntAdd這個函數,按F12跳轉或右鍵-->"轉到定義",可以看到來到了.h的宣告中,說明此時使用的就是自己的.dll中的函數。:>


  • 總結

不難,但是需要思路清晰。大家加油!