大型應用程式由多模組組成,各模組完成獨立功能並協作。若將所有原始碼靜態編譯進 EXE,會導致:檔案體積膨脹、記憶體佔用大、編譯時間長、不利單元測試。Windows 提供 DLL (Dynamic Linkable Library) 機制:獨立編譯測試、執行時按需載入、多程式共用、減少資源浪費。Windows 核心功能多以 DLL 實現(如 IE 核心元件可被其他程式呼叫)。
__declspec(dllexport) int MyFunction(int n);
__declspec(dllimport) int MyFunction(int n);
// MyDLL.h
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
MYDLL_API int MyFunction(int n);
; MyDLL.def
LIBRARY "MyDLL"
EXPORTS
MyFunction @1
但 .def 易引發更多問題,建議使用 __declspec。
| 特性 | 隱式連結 | 顯式連結 |
|---|---|---|
| 程式碼中指定 DLL 路徑 | 否 | 是 (LoadLibrary 參數) |
| 開發者關心 DLL 載入時機 | 否 | 是 |
| 自動產生 .lib 匯入庫 | 是 | 否 |
| 載入時機 | EXE 載入時 | 呼叫 LoadLibrary 時 |
| 適用語言 | C/C++ 原生 | VB、C#、動態載入需求 |
// DLL 匯出
extern "C" __declspec(dllexport) double SquareRoot(double d);
// 應用程式顯式連結
typedef double (SQRTPROC)(double);
HINSTANCE hInstance;
SQRTPROC* pFunction;
VERIFY(hInstance = ::LoadLibrary("c:\\winnt\\system32\\mydll.dll"));
VERIFY(pFunction = (SQRTPROC*)::GetProcAddress(hInstance, "SquareRoot"));
double d = (*pFunction)(81.0); // 呼叫 DLL 函式
HINSTANCE g_hInstance;
extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
TRACE0("DLL Initializing!\n");
g_hInstance = hInstance;
// 初始化:DisableThreadLibraryCalls(hInstance) 可優化
break;
case DLL_THREAD_ATTACH:
// 執行緒建立(若未 DisableThreadLibraryCalls)
break;
case DLL_THREAD_DETACH:
// 執行緒結束
break;
case DLL_PROCESS_DETACH:
TRACE0("DLL Terminating!\n");
// 清理資源
break;
}
return TRUE; // 成功
}
未提供 DllMain 時系統引入無操作預設版本。單一執行緒啟動/結束也會呼叫。
HINSTANCEHINSTANCE == HMODULE 可互換0x00400000,DLL 預設 0x10000000// 取得 EXE 模組控制代碼
HINSTANCE hExe = GetModuleHandle(NULL);
// 取得 DLL 模組控制代碼
HINSTANCE hDll = GetModuleHandle("MyDLL.dll");
FindResource 需 HINSTANCE 參數指定資源來源模組。EXE/DLL 各有獨立資源,需正確指定。
System32)VC++ 專案建立 DLL,複製至系統目錄供應用程式呼叫。修改 DLL 重建後忘記更新系統目錄副本 → 應用程式仍載入舊版本。解決:輸出目錄設為應用程式目錄、或使用延遲載入、或建置後自動複製。
OutputDebugString/TRACE 輸出診斷資訊ntdll!LdrLoadDll、ntdll!LdrUnloadDllVS_VERSION_INFO 嵌入版本資訊/DELAYLOAD 連結器選項,首次呼叫時載入LoadLibraryEx 配合 LOAD_LIBRARY_SEARCH_* 旗標防止 DLL 劫持