靜態調用或顯示裝載
使用一個外部聲明子句使DLLs在應用程序開始執行前即被裝入例如
function Instr(SourceStr : PChar;Check : Char) Integer; far; external UseStr;
使用這種方法程序無法在運行時間裡決定DLLs的調用假如一個特定的DLLs在運行時無法使用則應用程序將無法執行
動態調用或隱式裝載
使用Windows API函數LoadLibray和GetProcAddress可以實現在運行時間裡動態裝載DLLs並調用其中的過程
若程序只在其中的一部分調用DLLs的過程或者程序使用哪個DLLs 調用其中的哪個過程需要根據程序運行的實際狀態來判斷那麼使用動態調用就是一個很好的選擇
使用動態調用即使裝載一個DLLs失敗了程序仍能繼續運行
靜態調用
在靜態調用一個DLLs中的過程或函數時external指示增加到過程或函數的聲明語句中被調用的過程或函數必須采用遠調用模式這可以使用far過程指示或一個{$F +}編譯指示
Delphi全部支持傳統Windows動態鏈接庫編程中的三種調用方式它們是
● 通過過程/函數名
● 通過過程/函數的別名
● 通過過程/函數的順序號
通過過程或函數的別名調用給用戶編程提供了靈活性而通過順序號(Index)調用可以提高相應DLL的裝載速度
動態調用
動態調用中的API函數
動態調用中使用的Windows API函數主要有三個即LoadlibraryGetProcAddress和Freelibrary
Loadlibrary: 把指定庫模塊裝入內存
語法為
function Loadlibrary(LibFileName: PChar) THandle;
LibFileName指定了要裝載DLLs的文件名如果LibFileName沒有包含一個路徑則Windows按下述順序進行查找
()當前目錄
()Windows目錄(包含wincom的目錄)函數GetWindowDirectory返回這一目錄的路徑
()Windows系統目錄(包含系統文件如gdiexe的目錄)函數GetSystemDirectory返回這一目錄的路徑
()包含當前任務可執行文件的目錄利用函數GetModuleFileName可以返回這一目錄的路徑
()列在PATH環境變量中的目錄
()網絡的映象目錄列表
如果函數執行成功則返回裝載庫模塊的實例句柄否則返回一個小於HINSTANCE_ERROR的錯誤代碼錯誤代碼的意義如下表
表 Loadlibrary返回錯誤代碼的意義
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
錯誤代碼 意 義
系統內存不夠可執行文件被破壞或調用非法
文件沒有被發現
路徑沒有被發現
企圖動態鏈接一個任務或者有一個共享或網絡保護錯
庫需要為每個任務建立分離的數據段
沒有足夠的內存啟動應用程序
Windows版本不正確
可執行文件非法或者不是Windows應用程序或者在EXE映像中有錯誤
應用程序為一個不同的操作系統設計(如OS/程序)
應用程序為MS DOS設計
可執行文件的類型不知道
試圖裝載一個實模式應用程序(為早期Windows版本設計)
試圖裝載包含可寫的多個數據段的可執行文件的第二個實例
試圖裝載一個壓縮的可執行文件文件必須被解壓後才能被裝裁
動態鏈接庫文件非法
應用程序需要位擴展
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
假如在應用程序用Loadlibrary調用某一模塊前其它應用程序已把該模塊裝入內存則Loadlibrary並不會裝載該模塊的另一實例而是使該模塊的引用計數加
GetProcAddress:撿取給定模塊中函數的地址
語法為
function GetProcAddress(Module: THandle; ProcName: PChar) TFarProc;
Module包含被調用的函數庫模塊的句柄這個值由Loadlibrary返回如果把Module設置為nil則表示要引用當前模塊
ProcName是指向含有函數名的以nil結尾的字符串的指針或者也可以是函數的次序值如果ProcName參數是次序值則如果該次序值的函數在模塊中並不存在時GetProcAddress仍返回一個非nil的值這將引起混亂因此大部分情況下用函數名是一種更好的選擇如果用函數名則函數名的拼寫必須與動態鏈接庫文件EXPORTS節中的對應拼寫相一致
如果GetProcAddress執行成功則返回模塊中函數入口處的地址否則返回nil
Freelibrary:從內存中移出庫模塊
語法為
procedure Freelibrary(Module : THandle)
Module為庫模塊的句柄這個值由Loadlibrary返回
由於庫模塊在內存中只裝載一次因而調用Freelibrary首先使庫模塊的引用計數減一如果引用計數減為則卸出該模塊
每調用一次Loadlibrary就應調用一次FreeLibray以保證不會有多余的庫模塊在應用程序結束後仍留在內存中
動態調用舉例
對於動態調用我們舉了如下的一個簡單例子系統一共包含兩個編輯框在第一個編輯框中輸入一個字符串而後在第二個編輯框中輸入字符如果該字符包含在第一個編輯框的字符串中則標簽框顯示信息位於第n位否則顯示信息不包含這個字符如圖是程序的運行界面
輸入檢查功能的實現在Edit的OnKeyPress事件處理過程中程序清單如下
procedure TFormEditKeyPress(Sender: TObject; var Key: Char)
var
order: Integer;
txt: PChar;
PFunc: TFarProc;
Moudle: THandle;
begin
Moudle := Loadlibrary(c:\dlls\exampledll)
if Moudle > then
begin
Edittext := ;
Pfunc := GetProcAddress(MoudleInstr)
txt := StrAlloc()
txt := StrPCopy(txtEdittext)
Order := TInstr(PFunc)(txtKey)
if Order = then
LabelCaption := 不包含這個字符
else
LabelCaption := 位於第+IntToStr(Order+)+位;
end;
Freelibrary(Moudle)
end;
在利用GetProcAddess返回的函數指針時必須進行強制類型轉換
[] [] [] []
From:http://tw.wingwit.com/Article/program/Delphi/201311/25209.html