本文系統總結 Delphi 調用 DLL 的兩大核心模式——靜態與動態呼叫,深度解析 LoadLibrary、GetProcAddress、FreeLibrary 三大 API 參數與錯誤碼,並以字串搜尋函式為例完整示範動態呼叫實戰代碼。
| 模式 | 機制 | 優點 | 缺點 |
|---|---|---|---|
| 靜態呼叫 (顯式載入) | external 宣告,應用啟動前載入 DLL | 程式碼簡潔,直接像呼叫本地函式 | 啟動即依賴 DLL,缺失則無法執行;無法運行時動態決定 |
| 動態呼叫 (隱式載入) | 運行時呼叫 LoadLibrary / GetProcAddress | 可條件載入、失敗不影響主程式、支援插件架構 | 代碼較繁瑣,需手動管理載入/釋放 |
function Foo: Integer; far; external 'MyDLL';function Foo: Integer; far; external 'MyDLL' name 'RealFoo';(彈性命名)function Foo: Integer; far; external 'MyDLL' index 5;(載入速度最快)所有被呼叫函式必須採用 far 遠呼叫模式(或 {$F+} 指令)。
function LoadLibrary(LibFileName: PChar): THandle;
搜尋順序:當前目錄 → Windows 目錄 → System 目錄 → 應用程式目錄 → PATH 環境變數 → 網路路徑。
成功返回模組實例句柄(>32),失敗返回錯誤碼(<32)。常見錯誤碼:
若模組已在記憶體,LoadLibrary 僅增加「引用計數」,不重複載入。
function GetProcAddress(Module: THandle; ProcName: PChar): TFarProc;
Module:LoadLibrary 返回的句柄(nil 表當前模組)。ProcName:函式名稱字串**或**序數值。建議使用名稱避免序數不存在時仍返回非 nil 導致誤判。nil。procedure FreeLibrary(Module: THandle);
遞減引用計數,歸零時真正卸載。**每次 LoadLibrary 必須配對一次 FreeLibrary**,防止殘留模組佔用記憶體。
場景:輸入字串與單一字元,呼叫 DLL 中 Instr 函式搜尋字元位置。
procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char);
var
Order: Integer; txt: PChar; PFunc: TFarProc; Module: THandle;
begin
Module := LoadLibrary('c:\dlls\example.dll');
if Module > 32 then begin
Edit2.Text := '';
PFunc := GetProcAddress(Module, 'Instr');
txt := StrAlloc(80);
StrPCopy(txt, Edit1.Text);
Order := TInstr(PFunc)(txt, Key); // 關鍵:函式指標強制轉型
if Order = -1 then
Label1.Caption := '不包含這個字符'
else
Label1.Caption := '位於第 ' + IntToStr(Order + 1) + ' 位';
end;
FreeLibrary(Module);
end;
關鍵技巧:TFarProc 必須轉型為具體函式類型再呼叫:
type TInStr = function(Source: PChar; Check: Char): Integer;
Order := TInStr(PFunc)(txt, Key);
掌握靜/動態呼叫精髓與 API 細節,即能靈活構建模組化、可擴展的 Delphi 系統架構。