首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

VS2013 C++ DLL 編寫與導入完整教程:從空專案到跨模組調用

     編輯:程式設計綜合問答

核心概念釐清

類型產出檔案連結方式執行時需求適用場景
靜態庫.lib編譯期嵌入 .exe無額外檔案工具函數、數學庫、體積小
動態庫.dll + .lib (導入庫)編譯期鏈接 .lib,運行期載入 .dll需部署 .dll大型模組、插件系統、跨語言調用、熱更新

判別方法:`dumpbin /exports xxx.dll` 查看導出表;`.lib` 若含 COFF 符號表且無代碼段為導入庫,若含代碼段為靜態庫。

步驟一:建立 DLL 專案 (最簡單類別)

  1. VS2013 → 新建專案 → Visual C++ → Win32 → Win32 Console Application (或 Win32 Project)。
  2. 精靈 → Application type: DLL、勾選 Empty project → 完成。
  3. 新增頭文件 `MyMath.h`:

// MyMath.h
#pragma once

#ifdef MYMATH_EXPORTS
#define MYMATH_API __declspec(dllexport)
#else
#define MYMATH_API __declspec(dllimport)
#endif

// 簡單類別導出
class MYMATH_API Calculator {
public:
    Calculator();
    int Add(int a, int b);
    int Subtract(int a, int b);
};

// 全域函數導出 (C 風格,跨語言友好)
extern "C" MYMATH_API int Multiply(int a, int b);
  1. 新增源文件 `MyMath.cpp`:

// MyMath.cpp
#include "MyMath.h"

Calculator::Calculator() {}

int Calculator::Add(int a, int b) { return a + b; }
int Calculator::Subtract(int a, int b) { return a - b; }

extern "C" int Multiply(int a, int b) { return a * b; }
  1. 專案屬性 → C/C++ → Preprocessor → Preprocessor Definitions 添加 MYMATH_EXPORTS (僅 DLL 專案需定義)。
  2. 建置 → 生成 `MyMath.dll`、`MyMath.lib`、`MyMath.h`。

步驟二:客戶端專案導入 DLL (兩種方式)

方式 A:隱式鏈接 (推薦,編譯期綁定)

  1. 新建 Console Application 專案。
  2. 複製 `MyMath.h`、`MyMath.lib` 到專案目錄 (如 `../MyMath/`)。
  3. 專案屬性 → Linker → General → Additional Library Directories 添加 `$(SolutionDir)MyMath\`。
    Linker → Input → Additional Dependencies 添加 `MyMath.lib`。
  4. C/C++ → General → Additional Include Directories 添加 `$(SolutionDir)MyMath\`。
  5. 客戶端代碼 `main.cpp`:

#include 
#include "MyMath.h"
#pragma comment(lib, "MyMath.lib") // 替代屬性頁設定

int main() {
    Calculator calc;
    std::cout << "Add: " << calc.Add(10, 5) << std::endl;       // 15
    std::cout << "Multiply: " << Multiply(3, 7) << std::endl;   // 21
    return 0;
}

運行時:將 `MyMath.dll` 複製到客戶端 `.exe` 同目錄 (或系統 PATH 目錄)。

方式 B:顯式載入 (Run-time Dynamic Linking,無需 .lib/.h)


#include 
#include 

typedef int (*PFN_Multiply)(int, int);
// 類別無法直接顯式載入,需導出 C 風格工廠函數
// extern "C" MYMATH_API Calculator* CreateCalculator();
// typedef Calculator* (*PFN_CreateCalc)();

int main() {
    HMODULE hDll = LoadLibrary(L"MyMath.dll");
    if (!hDll) { std::cerr << "Load DLL failed: " << GetLastError(); return 1; }
    
    PFN_Multiply pMultiply = (PFN_Multiply)GetProcAddress(hDll, "Multiply");
    if (pMultiply) std::cout << "3*7=" << pMultiply(3,7) << std::endl;
    
    FreeLibrary(hDll);
    return 0;
}

常見坑點與解決

問題原因解決
LNK2019 無法解析外部符號未鏈接 .lib 或 .lib 路徑錯誤檢查 Linker → Input → Additional Dependencies
運行時「找不到 xxx.dll」DLL 不在搜尋路徑複製 DLL 到 exe 目錄或安裝至 System32
類別導出無法跨編譯器 (VS vs MinGW)C++ ABI 不兼容 (Name Mangling、虛表佈局)導出 C 風格介面 (`extern "C"`) + 純虛類別介面
Debug/Release 混用崩潰CRT 版本不匹配 (MSVCRTD vs MSVCRT)統一編譯配置,或使用 `/MD` 動態 CRT

最佳實踐總結

  • 頭文件使用 #pragma once + 宏控制 `dllexport/dllimport`。
  • 導出介面盡量用 C 風格函數 + 不透明指針 封裝 C++ 類別,保證二進制兼容。
  • 提供 Create/Destroy 工廠函數,避免跨模組 `new`/`delete` 不匹配。
  • 版本資源嵌入 DLL (VS 版本資源),便於部署檢查。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved