tft每日頭條

 > 科技

 > 動态鍊接庫的建立與調用實驗分析

動态鍊接庫的建立與調用實驗分析

科技 更新时间:2024-12-21 11:10:23
4.動态鍊接庫的動态調用

動态調用也稱為顯式加載方式,動态調用不需要在單元體 Interface 部分把需要調用的所有 dll 過程全部列出,隻要在調用前引用,并且使用 LoadLibrary 函數指定需要加載的 dll 文件,使用 GetProcAddress 函數指定所調用的過程或函數,并返回該過程或函數的入口地址,使用 FreeLibrary 函數實現将該函數從内存中移除。

如果指定的 dll 文件出錯,不會導緻程序終止運行。

動态調用 dll 主要用到三個 Win32 API 函數:

1.LoadLibrary() - 把指定庫模塊裝入内存,語法:

function LoadLibrary(LibFileName: PChar): THandle;

LibFileName 指定了要裝載 dll 的文件名,如果 LibFileName 沒有包含一個路徑,則 Windows 按如下順序進行查找:

  • 當前目錄
  • Windows 目錄
  • Windows 系統目錄
  • 當前可執行文件所在目錄
  • PATH 環境變量中的目錄以及網絡的映像目錄列表

如果函數執行成功,則返回裝載庫的實例句柄。否則,返回一個小于 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,則卸載該模塊。

示例:使用上一節中的角度轉換弧度的動态鍊接庫,實現輸入角度,輸出弧度。界面如下:

動态鍊接庫的建立與調用實驗分析(14.動态鍊接庫編程)1

代碼如下:

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每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved