動態連結庫(DLL)讓多個進程共享同一份程式碼,減少記憶體佔用。本文系統闡述 DLL 函數宣告規範、連結模式、跨語言呼叫慣例,並給出可直接用於專案的統一標頭檔範本。
__declspec(dllexport):標記 DLL 導出函數/類別/變數。__declspec(dllimport):標記客戶端導入宣告,產生間接跳轉指令,提升效能。extern "C":強制使用 C 連結慣例,避免 C++ 名稱修飾,確保 C/C++/其他語言均可呼叫。extern "C"):函數名稱保持原樣,適合跨語言、動態載入(GetProcAddress)。實務上強烈建議統一採用 C 連結,以最大化相容性。
早期做法:DLL 專案用 dllexport 標頭,客戶端用 dllimport 標頭,維護兩份檔案。進階做法:定義控制巨集 _DLLMODULENAME_,單一標頭檔雙向服務。
MyDll.h#ifndef _MYDLL_H
#define _MYDLL_H
#include <windows.h> // 必要系統標頭
#ifdef __cplusplus
extern "C" {
#endif
// 控制巨集:DLL 專案定義 _MYDLL_,客戶端不定義
#ifdef _MYDLL_
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
// 導出/導入函數宣告
MYDLL_API int MyFunc1(int a, double b);
MYDLL_API void MyFunc2(const char* msg);
// ... 更多宣告
#undef MYDLL_API
#ifdef __cplusplus
}
#endif
#endif // _MYDLL_H
#include "stdafx.h"
#define _MYDLL_
#include "MyDll.h"
int MyFunc1(int a, double b) { return a + (int)b; }
void MyFunc2(const char* msg) { puts(msg); }
.lib:#include "MyDll.h"
#pragma comment(lib, "MyDll.lib")
int main() { MyFunc1(1, 2.5); MyFunc2("Hello DLL"); }
MYDLL_API,所有成員函數自動導出。inline 函數實作,防止多重定義連結錯誤。遵循此規範,可構建乾淨、可維護、跨語言友善的 DLL 介面。