| 類型 | 產出檔案 | 連結方式 | 執行時需求 | 適用場景 |
|---|---|---|---|---|
| 靜態庫 | .lib | 編譯期嵌入 .exe | 無額外檔案 | 工具函數、數學庫、體積小 |
| 動態庫 | .dll + .lib (導入庫) | 編譯期鏈接 .lib,運行期載入 .dll | 需部署 .dll | 大型模組、插件系統、跨語言調用、熱更新 |
判別方法:`dumpbin /exports xxx.dll` 查看導出表;`.lib` 若含 COFF 符號表且無代碼段為導入庫,若含代碼段為靜態庫。
// 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);
// 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; }
MYMATH_EXPORTS (僅 DLL 專案需定義)。
#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 目錄)。
#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`。Create/Destroy 工廠函數,避免跨模組 `new`/`delete` 不匹配。