Package的優(yōu)點
Package的缺點
Package種類當用戶運行應(yīng)用程序時,運行時程序包提供功能。 設(shè)計時程序包用于在IDE中安裝組件并為自定義組件創(chuàng)建特殊的屬性編輯器。 單個包可以在設(shè)計時和運行時均起作用,并且設(shè)計時包經(jīng)常通過在其require子句中引用運行時包來工作。
Package文件說明BPL 英文全稱 Borland Package library ,是一種特殊的DLL文件,用于代碼重用和減少可執(zhí)行文件。編譯bpl時,僅需要添加相應(yīng)功能的pas文件,如果有窗體,則需要添加dfm文件。既然是DLL文件,那就是在運行時所需要的文件。BPL相當于C++中的DLL DCP 英文全稱:delphi compiled package,是 package 編譯時跟 bpl 一起產(chǎn)生出來的,記錄著 package 中公開的 class、procedure、function、variable、const.... 等等的名稱和相對位置。如果 某個控件包 A 引用了 控件包 B,當 控件包 A 編譯時,需要 控件包 B.dcp,若 控件包 B 有修改,更改了公開的界面,則 控件包 A 必須在 控件包 B 編譯之后重新編譯,以引用新的 B.dcp。否則,當 控件包 A 執(zhí)行時,執(zhí)行到引用自 控件包 B 的內(nèi)容時,就會出現(xiàn)錯誤。DCP相當于C++中的Lib,編譯時需要。 DCU 英文全稱:Delphi Compiled Unit File,是delphi單元文件.pas文件編譯后產(chǎn)生的文件,感覺沒有太大用處。 Package加載方式Package中的代碼 unit Unit2;interfaceuses Vcl.Dialogs;//函數(shù)案例function add(Num1, Num2: Integer): Integer; stdcall;//過程案例procedure ShowMsg(Str: String); stdcall;type//類的案例 TUser = class public function ShowString(): string; end; // 需要像DLL一樣聲明導(dǎo)出函數(shù)的列表,如果是靜態(tài)導(dǎo)入此項可以省略exports add, ShowMsg;implementationprocedure ShowMsg(Str: String);begin showmessage(Str);end;function add(Num1, Num2: Integer): Integer;begin Result := Num1 + Num2;end;{ TUser }function TUser.ShowString: string;begin Result := 'HelloWorld';end;end. 靜態(tài)加載一般大家在用Delphi時都是使用『靜態(tài)載入』, 像VCL的Package就是這種方式, 這種方式的好處是設(shè)計者不用去理會Package 的載入和釋放, 其實設(shè)計者根本感覺不到設(shè)用這項技術(shù); 當然也可以手動將Package加入到項目中『project->Options->Packages->Build with runtime packages中加入Package Name彼此的分隔符是分號』 動態(tài)載入代碼基本上是無痛使用,只要路徑配置沒有問題,基本上和使用普通單元沒有區(qū)別
動態(tài)加載動態(tài)加載和靜態(tài)加載相反,無論是載入還是釋放都要自己來處理,看起來好像是動態(tài)載入,這種方式個人感覺相當麻煩,雖然本質(zhì)上和dll的動態(tài)加載一樣,但是因為在導(dǎo)入的元素中多了類的概念,所以還需要使用反射的方式創(chuàng)建類的對象才能實現(xiàn)類成員的引用 implementationuses rtti, System.StrUtils;{$R *.dfm}procedure TForm1.Button2Click(Sender: TObject);var // 聲明和Package導(dǎo)出列表中一致結(jié)構(gòu)的過程 add01: procedure(Msg: String); stdcall; // 聲明和Package導(dǎo)出列表中一致結(jié)構(gòu)的函數(shù) add02: function(Num1: Integer; Num2: Integer): Integer; stdcall;begin // 載入bpl格式的Package var PackageHandle := LoadPackage('Package1.bpl'); if PackageHandle <> 0 then begin // 載入成功之后獲取對應(yīng)函數(shù)、過程的指針 @add01 := GetProcAddress(PackageHandle, 'ShowMsg'); @add02 := GetProcAddress(PackageHandle, 'add'); if @add01 <> nil then begin // 調(diào)用 add01('HelloWorld'); showmessage(add02(1, 2).Tostring); end; end; // 對于類我們需要先創(chuàng)建類的對象然后才可以實現(xiàn)類中函數(shù)的調(diào)用 var // 創(chuàng)建運行期上下問對象 rc := TRttiContext.create; var // 載入對應(yīng)單元中的類,注意此處需要寫單元名+類名 ClassType := rc.FindType('Unit2.TUser'); var // 獲取元類實例(對象) Instance := ClassType.AsInstance; var // 獲取該實例的元信息類型 QRClass := Instance.MetaclassType; var // 獲取用于創(chuàng)建TUser類型的構(gòu)造方法 CreateMethod := Instance.GetMethod('Create'); var // 利用獲取到的構(gòu)造方法對象,創(chuàng)建TUser類對象 User := CreateMethod.Invoke(QRClass, []); var // 函數(shù)調(diào)用 rs := ClassType.GetMethod('ShowString').Invoke(User, []); // 顯示返回值 showmessage(rs.asstring); //卸載包 UnloadPackage(PackageHandle);end;
動態(tài)載入?yún)⒖即a我在搜索Package相關(guān)內(nèi)容的使用看到下面這段代碼,它也可以實現(xiàn)創(chuàng)建類的對象,只是中間出現(xiàn)的類型的強制轉(zhuǎn)換,個人不是特別推薦,只是記錄一下作為筆記參考
官方參考文檔官方文檔是英文的,我也是翻看+翻譯讀了很久挑了幾篇有用的
|
|