熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Delphi編程 >> 正文

DelphiforLinux中應用共享對象庫

2013-11-23 17:29:47  來源: Delphi編程 
本文用通俗易懂的語言介紹Linux平台上共享對象庫(SO)的基本概念及主要優點通過剖析在Delphi for Linux中應用SO與在Delphi for Windows中應用DLL的異同以編程實例講述了Linux平台的SO庫文件的組成SO庫文件的函數重載特殊編譯指令采用Delphi for Linux創建SO的編程規則使用前的Linux系統設置以及在Delphi for Linux中用隱式或顯式鏈接方法裝入和使用SO函數的基本方法經驗及技巧並對應用SO可能出現的問題進行了探討和分析
  
  共享對象庫基本概念
  Delphi for Linux是Borland公司推出的基於Linux平台的面向對象的可視化開發工具是目前Linux平台上很好的應用開發工具Delphi for Linux也稱Kylix大家用Kylix開發Linux應用程序時可能使用過Linux操作系統本身帶的大量SO文件SO是一種特殊的運行文件包含若干方法對象和資源它不能直接運行但可以被Kylix應用程序或其它可執行文件動態調用SO文件擴展名為so編譯前源文件擴展名為dpr本文所舉例子均在Red Hat Linux 及Kylix 環境下調試編譯通過並可正常運行
  
  圖是Kylix主程序與SO庫的層次關系圖從中可看出使用SO庫有以下幾個優點
  

  
Kylix主程序與SO庫的層次關系圖

  
  ◆ 多個Kylix程序或它的多個單元文件可通過接口共用一個SO庫文件另一方面某一個Kylix程序可通過多個接口使用多個SO庫文件這樣SO變成一種可共用的資源實現真正的資源共享大大縮小了Kylix應用程序的執行代碼增強了軟件的可重用性
  
  ◆ 將SO文件作為Kylix應用程序的公共調用模塊設計時由於其獨立於應用程序軟件升級時只需修改SO庫文件及編譯SO無需更改及重編譯Kylix應用主程序
  
  ◆ 不僅可使用Kylix編寫SO庫還可使用C或C++等常用語言來編寫只要遵循特定的接口規范
  
  共享對象庫的創建
  SO庫文件的構成
  
  SO庫文件和Kylix標准單元文件的內部結構基本相同也有聲明實現及初始化部分區別之一在於SO庫只是其它程序可以調用的方法(包括函數及過程)集合區別之二庫程序以library關鍵字而非project開頭啟動其項目文件庫程序包含有exports語句其列出要向外部提供的導出函數及過程下面是SO庫文件代碼的簡單例子用以說明其構成
  
  library MyFirstSO
  uses
   SysUtils classes { Delphi for Windows 中引用類庫為Windows }
  function Add (ACharBChar)Integercdecloverload
  begin
   Result := Ord (A) + Ord (B)
  end
  function Add (AIntegerBInteger)Integercdecloverload
  begin
   Result := A + B
  end
  function Double (NInteger)Integercdecl
  begin
   Result := N *
  end;
  exports
   Add (AIntegerBInteger)
   Add (ACharBChar) name AddChar
   Double
  
  SO庫文件中的函數重載
  
  SO庫也可以使用重載函數(即多個函數使用相同名稱不同參數)使用時需在重載的函數聲明後標上overload指令Kylix可以用原名稱導出一個重載函數在exports從句中表示其參數表若要導出多個重載函數則要在exports從句中用name字句指定不同名稱以區別重載這可從上面的例子MyFirstSO中看出Add是重載函數為調用時區分一個用原函數聲明Add導出另一個用AddChar導出
  
  SO庫的特殊編譯指令
  
  編譯後生成的SO庫運行文件使用lib前綴和so擴展名考慮到實際命名規則與版本和支持符號鏈Kylix在Object Pascal語言中引入了幾個特殊編譯指令這些在Delphi中沒有什麼意義庫源文件MyFirstSOdpr編譯後產生的執行文件為libMyFirstSOso
  
  ◆ $SOPREFIX 改變名稱前綴默認為lib(正常庫)或bpl(Kylix包)用前綴區別兩種庫是因為Linux的庫用單一擴展(so)
  
  ◆ $SOSUFFIX 在庫名與擴展名之間增加文本指定版本或其它信息
  
  ◆ $SOVERSION 在擴展名之後增加版本號
  
  ◆ $SONAME 表示相關符號鏈名由編譯器自動生成
  
  例如下列代碼生成庫libsimpleso和符號鏈libsimpleso
  
  library simple
  uses
  SysUtilsClasses
  //函數定義省略
  {$SOVERSION }
  {$SONAME libsimpleso}
  
  共享對象庫的使用
  Kylix應用程序使用SO庫時可以采用兩種方式一種是隱式鏈接(Implicit linking)也稱靜態裝入另一種是顯式鏈接(Explicit Linking)也稱動態裝入下面分別介紹這兩種鏈接方式的使用方法技巧及將窗體對象放入SO庫的技術
  
  使用前的系統設置
  
  自定義SO庫建好後Kylix應用程序調用時會報錯這是因為Kylix找不到新建庫必須對系統進行相關設置這與在Delphi for Windows中使用DLL庫不同DLL庫建好後只需將編譯後的DLL文件放到Delphi主程序目錄下即可使用操作步驟如下
  
  ◆ 將編譯好的SO庫文件放到Linux系統庫目錄/lib或/usr/lib下或者在Linux系統庫路徑shell變量LD_LIBRARY_PATH中加入自定義SO庫文件所在路徑
  
  ◆ 在根用戶(root)下用ldconfig命令刷新庫緩沖區
  
  ◆ 對Kylix執行文件使用ldd命令查看該程序所關聯的SO庫
  
  隱式鏈接
  
  隱式鏈接是指在應用程序開始執行時就將SO庫文件加載到應用程序中實現隱式鏈接並不難只需在應用程序中加入庫函數的聲明語句及庫的external定義從句則庫函數可以和一般局部函數一樣使用比如要使用libMyFirstSOso中的Add函數則只要在應用程序中增加下面語句
  
  function Add (AIntegerBInteger)Integercdecl
  
  external libMyFirstSOso
  
  顯式鏈接
  
  顯式鏈接是應用程序在執行過程中可根據實際需要隨時加載SO庫文件也可以隨時卸載SO庫文件還可在運行時進行SO庫的切換而這些是隱式鏈接無法做到的與隱式鏈接相比顯式鏈接具有更大的靈活性
  
  在Kylix中要動態裝入庫和調用導出函數可以用Delphi仿真代碼或自然Linux方法下面分別介紹這兩種方法
  
  ()用Delphi仿真代碼動態裝入
  
  在Windows中動態裝入DLL是用Windows API函數—LoadLibrary或Delphi提供的SafeLoadLibrary函數完成的找到庫後程序調用Windows API函數—GetProcAddress搜索DLL導出函數若找到匹配則返回所請求函數指針並將這個函數指針轉換成適當類型和調用使用完後調用FreeLibrary從內存中釋放庫
  
  Kylix中使用Pascal RTL仿真函數實現SO庫動態裝入下面的例子只列出Kylix應用程序中與動態鏈接相關部分而非完整Kylix單元文件代碼
  
  unit DynaForm;
  interface
  uses
  SysUtilsClassesQcontrolsQforms
  type
   TForm = class(TForm)
  Button: TButton;
  procedure ButtonClick(Sender: TObject);
  end;
  var FormTForm
  implementation
  {$R *XFM}
  type TComputeInteger = function (xIntegeryInteger)Integercdecl
  //調用庫函數接口類型定義
  procedure TFormButtonClick(SenderTObject)
  var Handle Thandle
  Compute TcomputeInteger
  begin
   Handle:=LoadLibrary(libMyFirstSOso)//動態裝入庫
   if Handle<> then //找到庫
   begin
  Compute:=TcomputeInteger(GetProcAddress(HandleAdd)
  //搜索庫函數Add並返回函數指針
  if Assigned(Compute) then
    ShowMessage(IntToStr(Compute())//使用庫函數
  FreeLibrary(Handle)//釋放庫
   end
   else
  ShowMessage(Library not found)
  end
  
  ()用Linux自然代碼動態裝入
  
  也可以使用Libc系統單元中的低級Linux函數這樣可使用更多參數更好地控制系統使用的Linux函數分別為dlopen(打開並裝入庫函數)dlsym(搜索庫函數)dlclose(釋放庫)因此上例中調用庫的代碼變為
  
  procedure TFormButtonClick(SenderTObject)
  var Handle Pointer
  Compute TcomputeInteger
  begin
   Handle:=dlopen(libMyFirstSOso)//動態裝入庫
   if Handle<>nil then //找到庫
   begin
  Compute:=TcomputeInteger(dlsym(HandleAdd)
  //搜索庫函數Add並返回函數指針
  if Assigned(Compute) then
    ShowMessage(IntToStr(Compute())//使用庫函數
  dlclose(Handle)//釋放庫
   end
   else
  ShowMessage(Library not found)
  end
  
  ()SO庫中窗體對象的使用
  
  除了包含函數和過程的庫之外還可以將Kylix建立的窗體放在共享對象中這可以是對話框或其它窗體
  
  生成新的庫對象之後只要在庫源文件的聲明部分增加對窗體單元文件
From:http://tw.wingwit.com/Article/program/Delphi/201311/24683.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.