function Instr(SourceStr: PChar; Check: Char): Integer; far; external 'UseStr';
缺點:運行時無法決定調用,特定 DLL 不可用則應用無法執行。LoadLibrary/GetProcAddress 裝載並調用。適用:部分代碼調用 DLL、根據運行狀態決定用哪個 DLL/哪個過程。優點:裝載失敗程序仍可繼續運行。external 指示加在聲明中。被調用過程/函數必須採用遠調用模式(far 指示或 {$F+} 編譯指令)。Delphi 支持三種方式:
Index(提高裝載速度)| 函數 | 功能 | 語法 |
|---|---|---|
| LoadLibrary | 裝載庫模塊到內存 | function LoadLibrary(LibFileName: PChar): THandle; |
| GetProcAddress | 獲取模塊中函數地址 | function GetProcAddress(Module: THandle; ProcName: PChar): TFarProc; |
| FreeLibrary | 從內存卸載庫模塊 | procedure FreeLibrary(Module: THandle); |
LibFileName 無路徑時按序查找:① 當前目錄 ② Windows 目錄 ③ Windows 系統目錄 ④ 當前任務可執行文件目錄 ⑤ PATH 環境變量目錄 ⑥ 網絡映射目錄。成功返回實例句柄,失敗返回 HINSTANCE_ERROR 以下錯誤碼:
| 錯誤碼 | 含義 |
|---|---|
| 0 | 系統內存不足/可執行文件損壞/調用非法 |
| 2 | 文件未找到 |
| 3 | 路徑未找到 |
| 5 | 嘗試動態鏈接任務/共享網絡保護錯 |
| 6 | 庫需為每任務建立獨立數據段 |
| 8 | 內存不足啟動應用 |
| 10 | Windows 版本不正確 |
| 11 | 可執行文件非法/非 Windows 應用/映像錯誤 |
| 12 | 為其他操作系統設計(如 OS/2) |
| 13 | 為 MS-DOS 4.0 設計 |
| 14 | 可執行文件類型未知 |
| 15 | 嘗試裝載實模式應用(早期 Windows) |
| 16 | 嘗試裝載含可寫多數據段可執行文件第二實例 |
| 19 | 嘗試裝載壓縮可執行文件(需解壓) |
| 20 | DLL 文件非法 |
| 21 | 需 32 位擴展 |
若其他應用已裝載該模塊,LoadLibrary 不重複裝載,而是增加「引用計數」。
Module 為 LoadLibrary 返回句柄,nil 表示當前模塊。ProcName 為函數名指針或順序值。用順序值時若函數不存在仍返回非 nil 易混淆,推薦用函數名(拼寫須與 DLL EXPORTS 節一致)。成功返回函數入口地址,失敗返回 nil。
模塊內存僅裝載一次,調用遞減引用計數,歸零則卸載。每次 LoadLibrary 必配對 FreeLibrary,防止殘留模塊。
系統含兩編輯框:第一輸入字符串,第二輸入字符。若字符包含在字符串中,標簽顯示位置,否則提示不包含。Edit2.OnKeyPress 實現:
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);
txt := 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;
TInstr 為預定義函數類型:type TInstr = function(Source: PChar; Check: Char): Integer;