動态調用也稱為顯式加載方式,動态調用不需要在單元體 Interface 部分把需要調用的所有 dll 過程全部列出,隻要在調用前引用,并且使用 LoadLibrary 函數指定需要加載的 dll 文件,使用 GetProcAddress 函數指定所調用的過程或函數,并返回該過程或函數的入口地址,使用 FreeLibrary 函數實現将該函數從内存中移除。
如果指定的 dll 文件出錯,不會導緻程序終止運行。
動态調用 dll 主要用到三個 Win32 API 函數:
1.LoadLibrary() - 把指定庫模塊裝入内存,語法:
function LoadLibrary(LibFileName: PChar): THandle;
LibFileName 指定了要裝載 dll 的文件名,如果 LibFileName 沒有包含一個路徑,則 Windows 按如下順序進行查找:
如果函數執行成功,則返回裝載庫的實例句柄。否則,返回一個小于 HINSTANCE_ERROR 的錯誤代碼以指明錯誤的種類。
如果應用程序中使用 LoadLibrary 調用某一模塊前,其他應用程序已經把該模塊裝入内存,則 LoadLibrary 并不會裝載該模塊的另一實例,而是使該模塊的“引用計數”加 1 。這樣就能夠保證在内存中隻加載一次,所有應用程序都共享這個單一的拷貝。
2.GetProcAddress() - 獲取給定模塊中函數的地址,語法:
function GetProcAddress(Module: THandle; ProcName: PChar): TFarChar;
Module 包含被調用的函數庫模塊的句柄,該值由 LoadLibrary 返回。如果将 module 設置為 nil,則表示要引用當前模塊。
ProcName 是指向含有函數名的以 nil 結尾的字符串指針,該字符串指針中所含有的函數名的拼寫必須與動态鍊接庫文件 exports 中的對應拼寫一緻,否則會出錯。
如果該函數執行成功,則返回模塊中函數入口處的地址,否則返回 nil。
3.FreeLibrary() - 從内存中移出庫模塊,語法:
procedure FreeLibrary(Module: THandle);
Module 為庫模塊的句柄,由 LoadLibrary 返回。由于庫模塊在内存中隻裝載一次,因而調用該過程首先庫模塊的引用計數減 1。如果引用計數為 0,則卸載該模塊。
示例:使用上一節中的角度轉換弧度的動态鍊接庫,實現輸入角度,輸出弧度。界面如下:
代碼如下:
unit Unit1;
{$mode objfpc}{$H }
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Spin, Windows;
type
{ TForm1 }
TForm1 = class(TForm)
AngFloatSpinEdit: TFloatSpinEdit;
Button1: TButton;
Label1: TLabel;
Label2: TLabel;
ArcLabel: TLabel;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
type
// 照着DLL(在源文件中)所使用的定義的方式,定義将要調用的子程序
TFunAngToArc=function (a: double):double; stdcall;
{$R *.lfm}
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
var
// 為DLL子程序創建一個合适的變量(數據字段)
pfunc: TFunAngToArc;
// 為DLL創建一個處理程序/句柄
hdl: THandle;
begin
// 獲取将要使用的庫的處理程序/句柄
hdl:=LoadLibrary(PChar('laz1401.dll'));
// 檢查是否成功加載DLL文件
if hdl>32 then
begin
// 分配子程序調用的存儲器地址給變量
Pointer(pfunc):=GetProcAddress(hdl, 'FunAngToArc');
// 檢查是否已經返回一個有限的存儲器内存地址
if @pfunc <> nil then
ArcLabel.Caption:=floattostr(pfunc(AngFloatSpinEdit.Value));
end;
// 釋放存儲器内存
pfunc:=nil;
FreeLibrary(hdl);
end;
end.
更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!