转:以Delphi Package架构多人开发应用程序环境
?????轉(zhuǎn)自https://www.cnblogs.com/dingjie/articles/195195.html
本人編寫的另一實(shí)現(xiàn)BPL窗體嵌入主程序的Demo發(fā)布在我的個(gè)人網(wǎng)站,blog.hsuzo.cn,該文后有源碼。
-
印象中的Package
在一般的AP開發(fā)時(shí),我們知道在Delphi7.0整合環(huán)境中將Project->Options->選到Packages卷標(biāo)頁,Builder with runtime packages選項(xiàng)打勾,就會(huì)讓編譯出來的執(zhí)行文件Size變小很多(以空白的Form1為例,編譯出來的Size由367kb變成20kb),因?yàn)樗岩恍¬CL共享模塊的Loding放到*.bpl中;換句話說這個(gè)變小的EXE文件在執(zhí)行時(shí)是需要那些*.bpl的,而原本較大的執(zhí)行文件執(zhí)行時(shí)則不需要那些*.bpl,這樣看來其實(shí)只是換湯不換藥罷了。
這種編譯架構(gòu)的差異有什么優(yōu)點(diǎn)?試想,如果Project1.exe&Project2.exe都不使用Builder with runtime packages選項(xiàng),Project1.exe跟Project2.exe編譯出來的Size都是367kb,若有10個(gè)ProjectN.exe,則占用的Size將是全部exe加起來的總和,若是我們將其中共享的部分(如VCL共享模塊)獨(dú)立出來,每個(gè)EXE都將只有20K(以測試用的空白Form而言),缺點(diǎn)則只有每個(gè)exe執(zhí)行時(shí)都要在系統(tǒng)搜尋路徑中找得到那些VCL的共享模塊(以*.bpl文件名存在);所以這種架構(gòu)適用于一個(gè)項(xiàng)目系統(tǒng)內(nèi)有多個(gè)獨(dú)立執(zhí)行文件或獨(dú)立業(yè)務(wù)模塊存在的情況,多個(gè)執(zhí)行文件就可以分散給多個(gè)人去開發(fā),也可依照應(yīng)用程序不同的業(yè)務(wù)性質(zhì)去區(qū)隔并分別設(shè)計(jì)。
將執(zhí)行文件分散開來開發(fā),這種做法跟一個(gè)主執(zhí)行文件配合多個(gè)不同業(yè)務(wù)別的DLL開發(fā)沒有什么差別,而降低每支執(zhí)行文件的Size也只是Package最普通的應(yīng)用;使用Package有一個(gè)更強(qiáng)大的優(yōu)點(diǎn)——可以共享變量,如果將數(shù)據(jù)模塊當(dāng)成一個(gè)共享變量的觀念去看待,我們不用在每次啟動(dòng)或關(guān)閉不同的子系統(tǒng)業(yè)務(wù)模塊時(shí),重新連接或釋放數(shù)據(jù)庫的Connection。不過,要真正能共享數(shù)據(jù)庫模塊是需要每個(gè)業(yè)務(wù)模塊皆以*.bpl的方式存在,這也是實(shí)際應(yīng)用上的狀況。
| 項(xiàng)目架構(gòu)種類 | Package編譯方式 | 說明 |
| 類型一 Project0.exe(MIS主系統(tǒng)) Project1.exe(會(huì)計(jì)子系統(tǒng)) Project2.exe(人事子系統(tǒng)) Project3.exe(庫存子系統(tǒng)) | 所有EXE文件編譯選項(xiàng) □Builder with runtime packages | 1.每個(gè)子系統(tǒng)都是完整獨(dú)立的EXE文件;每個(gè)EXE文件至少都有數(shù)百KB以上 |
| 類型二 Project0.exe(MIS主系統(tǒng)) Project1.exe(會(huì)計(jì)子系統(tǒng)) Project2.exe(人事子系統(tǒng)) Project3.exe(庫存子系統(tǒng)) | VCL共享模塊(*.bpl) 所有EXE文件編譯選項(xiàng) ■Builder with runtime packages(打勾) | 1.每個(gè)子系統(tǒng)雖然都是EXE文件,但執(zhí)行時(shí)需要VCL的共享模塊存在;此種方式,每個(gè)EXE文件SIZE都只有幾十KB 2.此種架構(gòu)只有節(jié)省檔案SIZE的優(yōu)點(diǎn) |
| 類型三 Project0.exe(MIS主系統(tǒng)) Project1.bpl(會(huì)計(jì)子系統(tǒng)) Project2.bpl(人事子系統(tǒng)) Project3.bpl(庫存子系統(tǒng)) VCL共享模塊(*.bpl) DataMoudle(db.bpl) | 所有EXE文件編譯選項(xiàng) ■Builder with runtime packages(打勾) | 1.將各子系統(tǒng)中共享的程序(如連接數(shù)據(jù)庫的模塊)獨(dú)立出來共享 2.除主系統(tǒng)外其余子系統(tǒng)皆為BPL型式存在 3.節(jié)省檔案SIZE外,并有共 用數(shù)據(jù)庫連結(jié)模塊的優(yōu)點(diǎn) |
注:
1.MIS主系統(tǒng)(Project0.exe)可能只是一個(gè)選單(Menu),用來當(dāng)作啟動(dòng)各子系統(tǒng)的Shell
2.VCL共享模塊(*.bpl)是Delphi在安裝時(shí)即安裝至C:\WINNT\SYSTEM32\中的那些*.bpl檔案,不管你EXE文件是否Builderwithruntimepackages,那些*.bpl早已存在,端看你要不要用它而已(Builderwithruntimepackages是否打勾)
3.當(dāng)AP開發(fā)是以Builderwithruntimepackages(打勾)編譯時(shí),RELEASE到客戶端同時(shí)也要將C:\WINNT\SYSTEM32\中的那些*.bpl檔案COPY到客戶端,因?yàn)榭蛻舳藳]有安裝Delphi,所以沒有那些VCL共享模塊(*.bpl)
4.BPL跟EXE一樣是可以“LOAD”其它的*.bpl;如Project1.bpl(會(huì)計(jì)子系統(tǒng))會(huì)”LOAD”VCL共享模塊(*.bpl)以及DataMoudle(db.bpl)
5.在類型三中,作為唯一的EXE文件,Project0.exe編譯時(shí)一定要Builderwithruntimepackages(打勾),否則在動(dòng)態(tài)加載其它子系統(tǒng)模塊時(shí),會(huì)出現(xiàn)找不到類別的錯(cuò)誤
?
-
Package架構(gòu)的優(yōu)缺點(diǎn)
使用Package的優(yōu)點(diǎn):
1.類似DLL-應(yīng)用程序可以被高度的模塊化
2.優(yōu)于DLL之處-可以共享變量
使用Package的缺點(diǎn):
1.架構(gòu)較復(fù)雜,需要花比較多的心思在模塊化的設(shè)計(jì)
2.需要程度較高的開發(fā)人員,若對(duì)package的使用不熟,容易出trouble
?
-
哪些東西可以開發(fā)成為Package
前面講過,Package其實(shí)就是類似DLL的一種架構(gòu),但是是專門屬于Borland C++Builder/Delphi使用的一種DLL架構(gòu),舉凡有含F(xiàn)orm的Unit文件、無Form的Unit文件(如自己寫的函數(shù)庫)、組件等等,都可以編譯成為Package
Package檔案的類型
| ? | Package項(xiàng)目 | 相當(dāng)于一般項(xiàng)目 | 相當(dāng)于DLL項(xiàng)目 | |
| 編譯前 | *.DPK | Package項(xiàng)目文件 | DPR文件 | DPR文件 |
| *.PAS | PackageSource | PAS文件(Source) | PAS文件(Source) | |
| 編譯后(產(chǎn)出) | *.DCP | Package產(chǎn)出文件 | ? | LIB文件 |
| *.BPL | Package產(chǎn)出文件 | EXE文件 | DLL文件 | |
Package中的DCP文件,跟DLL項(xiàng)目的LIB文件類似,DCP是提供為靜態(tài)連結(jié)編譯之用(注意:只是靜態(tài)連結(jié)的“編譯過程”用之),BPL則是直接提供為執(zhí)行環(huán)境之用;DCP只有在提供給別的EXE或BPL靜態(tài)連結(jié)的“編譯過程”中會(huì)用到,所以不用RELEASE到客戶端;在執(zhí)行環(huán)境中,Package不管是被靜態(tài)聯(lián)結(jié)或是動(dòng)態(tài)連結(jié)使用,一律以BPL型式存在。
例如Project0.exe以“靜態(tài)連結(jié)”方式使用到Package1,Project0.exe在編譯時(shí)需要Package1.dcp的檔案存在,但編譯后分發(fā)到客戶端的檔案則為roject0.exe以及Package1.bpl(Package1.dcp不用release),雖然它們之間是使用靜態(tài)連結(jié)(加載)…
如果Project0.exe以“動(dòng)態(tài)連結(jié)”方式使用到Package1,Project0在編譯過程中根本不需要任何Package1的檔案,而分發(fā)到客戶端一樣仍然只有roject0.exe以及Package1.bpl。
?
Package的載入(從EXE載入BPL的角度來看)
靜態(tài)加載–不管用得用不到,該*.dcp是一定都要加載的,也就是在exe項(xiàng)目選項(xiàng)中的Builder with runtime packages->Add加入,如Project0.exe(MIS主系統(tǒng))一定要加載VCL共享模塊(*.dcp),否則無法產(chǎn)生GUI接口;所以就用靜態(tài)加載的方式加載它;靜態(tài)加載的*.dcp,是在編譯時(shí)就已決定的
動(dòng)態(tài)加載–使用到時(shí),才透過LoadPackage()這個(gè)API來呼叫,如Project0.exe(MIS主系統(tǒng))呼叫各個(gè)子系統(tǒng)的*.bpl,是透過Coding的方式去加載子系統(tǒng)的*.bpl,Project0.exe(MIS主系統(tǒng))并不需要在編譯時(shí)將所有子系統(tǒng)加載編譯
Package的載入(從BPL載入BPL的角度來看)
靜態(tài)加載–放在Package項(xiàng)目之Requires區(qū)段中的*.dcp文件,反正是“一定要用到”的,不需要利用動(dòng)態(tài)加載的就放在這兒
動(dòng)態(tài)加載–跟EXE動(dòng)態(tài)加載BPL方式相同,使用到時(shí),才透過Coding方式利用LoadPackage()這個(gè)API來加載的
?
-
Package項(xiàng)目的建立
在Delphi7.0整合環(huán)境中,主菜單->File->Close ALL關(guān)掉所有的Form及項(xiàng)目;然后再一次:主菜單->File->New->Other...->選擇Package,建立一個(gè)全新的Package項(xiàng)目
一個(gè)全新的Package應(yīng)該是長的如下圖所示,分為兩個(gè)部分:Contains內(nèi)放的是項(xiàng)目的主題,也就是我們要為這個(gè)Package開發(fā)的程序代碼;Require內(nèi)放的是要“靜態(tài)連結(jié)” 的其它Package(*.dcp文件),也就是不需要利用LoadPackage()這個(gè)API來加載(動(dòng)態(tài)加載)的Package就放到Require中;rtl.dcp是系統(tǒng)內(nèi)建就已Require的Package,應(yīng)該是VCL之類的東西吧
接下來我們要開始設(shè)計(jì)項(xiàng)目內(nèi)容,幫這個(gè)Package項(xiàng)目加入一個(gè)空白的Form,到Delphi主菜單->File->New->Form;我們?cè)倩氐絇roject Manager看看在Contains區(qū)段是否多了Unit1(Form1);前面說過,Contains內(nèi)放的是項(xiàng)目的主題,也就是我們要為這個(gè)Package開發(fā)的程序代碼,接下來要在Form1中放什么組件,寫什么程序代碼,都跟一般的Form沒什么兩樣,只是若這個(gè)Form是寫在一般的項(xiàng)目中(Project1.dpr)它可以被編譯成EXE文件,而在Package項(xiàng)目中(Package1.dpk),它只能被編譯成Package1.dcp(給別的項(xiàng)目靜態(tài)連結(jié)編譯時(shí)用)和Package1.bpl
Package1.dcp以及Package1.bpl這兩個(gè)編譯后的結(jié)果,Default是放到Delphi7.0目錄的.\Projects\Bpl\中;若要改變,請(qǐng)至Delphi主菜單->Project->Options(如下圖),修改項(xiàng)目的輸出目錄路徑為目前路徑(.\)
還有,很重要的一點(diǎn),在Package項(xiàng)目中的Form由于將來會(huì)被別人加載使用(不管被靜態(tài)或被動(dòng)態(tài)加載);它都需要先向系統(tǒng)注冊(cè)它的類別;所以在前面的例子中,將Unit1(Form1)開發(fā)好后,最后要在end.之前插入注冊(cè)(RegisterClass)/注銷(UnRegisterClass)的程序代碼,注冊(cè)內(nèi)容就是自己的Form類別(如TForm1、TForm2等等)
(其它程序代碼)............initializationRegisterClass(TForm1);finalizationUnRegisterClass(TForm1);end.?
-
Package的應(yīng)用限制
如果只是一個(gè)EXE文件附帶一個(gè)BPL文件,這種架構(gòu)還算單純,但如果如文章開始所述:一個(gè)MIS主系統(tǒng)(Project0.exe)帶著多個(gè)子系統(tǒng)(*.bpl),那會(huì)有什么限制發(fā)生呢?
1.各個(gè)Package(*.bpl)在開發(fā)過程中,彼此的Contains區(qū)段中不能有同名的Unit
2.共享的unit一定要放在package,也就是要把共享模塊變成Package
我們現(xiàn)在來想想,如果是我們來主導(dǎo)這個(gè)系統(tǒng),我們會(huì)如何設(shè)計(jì)呢?
1.雖然各項(xiàng)子系統(tǒng)是各自獨(dú)立開發(fā),甚至是交由不同的開發(fā)TEAM來完成,但為了接口的風(fēng)格一致及操作統(tǒng)一(如Button的大小及位置),我們會(huì)有一個(gè)共通的BaseForm的雛形,讓所有的子系統(tǒng)的主Form都由這個(gè)BaseForm繼承而來,這樣會(huì)讓子系統(tǒng)(Package)的Contains區(qū)段都會(huì)有一個(gè)共同uses的BaseForm.pas
2.為了程序代碼的一致性,也為了增加Coding速度,公司累積了程序代碼經(jīng)驗(yàn),可能會(huì)有一個(gè)公用副函數(shù)集MySub供各個(gè)子系統(tǒng)呼叫,這樣也會(huì)讓子系統(tǒng)(Package)的Contains區(qū)段都會(huì)有一個(gè)共同uses的MySub.pas
為了不讓BaseForm.pas及MySub.pas成為Package開發(fā)的限制瓶頸,所以我們要將BaseForm及MySub也變成Package(成為BaseForm.dcp及MySub.dcp),然后讓各個(gè)子系統(tǒng)Package放在Requires中靜態(tài)連結(jié)編譯。
?
-
Package的動(dòng)態(tài)加載
前面已介紹了Package在靜態(tài)加載以及編譯的方法,現(xiàn)在要介紹Package應(yīng)用的重頭戲-動(dòng)態(tài)加載;一般來說,共通的副函數(shù)或共享分享的數(shù)據(jù)庫模塊以及共享的繼承樣板會(huì)先被制作成Package,然后被主程序(EXE文件)及各個(gè)子系統(tǒng)模塊(BPL文件)作為靜態(tài)連結(jié)之用;而整個(gè)系統(tǒng)開發(fā)的主角,也就是各個(gè)子系統(tǒng)模塊會(huì)被主程序或子系統(tǒng)模塊(BPL文件)間,當(dāng)成動(dòng)態(tài)加載的目標(biāo)。
varModuleInstance1:HMODULE;{$R*.dfm}//---------------------------------------------------------------//動(dòng)態(tài)加載Package//---------------------------------------------------------------procedureTForm0.Button1Click(Sender:TObject);beginModuleInstance1:=LoadPackage('Package1.bpl');end;//---------------------------------------------------------------//將Package中的Form1帶出//---------------------------------------------------------------procedureTForm0.Button2Click(Sender:TObject);varfrm?:?TcustomForm;beginfrm :=CreateFormByClassName('TForm1');tryfrm.ShowModal;finallyfrm.Release;end;end;//---------------------------------------------------------------//釋放Package//---------------------------------------------------------------procedureTForm0.Button3Click(Sender:TObject);beginUnloadAddInPackage(ModuleInstance1);end;注:
1.在上列的程序代碼中,加載Package的LoadPackage()是系統(tǒng)內(nèi)建函數(shù)
2.帶出Package中的Form資源或是釋放Package的函數(shù)由于要多做一些處理,所以把它包在CreateFormByClassName()以及UnloadAddInPackage()兩個(gè)自訂函數(shù)中
//---------------------------------------------------------------//自訂函數(shù)–CreateFormByClassName(),建立Form//---------------------------------------------------------------Function?TForm0.CreateFormByClassName(const ClassName:string) : TCustomForm;varAClass:TPersistentClass;beginAClass:=GetClass(ClassName);If?AClass=nil then?exit;Result:=TComponentClass(AClass).Create(Application)?as?TCustomForm;//或Result:=TCustomForm(TComponentClass(AClass).Create(Application));end;//---------------------------------------------------------------//自訂函數(shù)–CreateDataModuleByClassName(),建立數(shù)據(jù)模塊//---------------------------------------------------------------Function?TForm0.CreateDataModuleByClassName(const?ClassName: string):TDataModule;varAClass:TPersistentClass;beginResult:=nil;AClass:=GetClass(ClassName);If?AClass=nil then?exit;Result:=TComponentClass(AClass).Create(Application)?as?TDataModule;end;//---------------------------------------------------------------//自訂函數(shù)–UnloadAddInPackage(),釋放Package//---------------------------------------------------------------Procedure?TForm0.UnloadAddInPackage(ModuleInstance:HMODULE);vari:Integer;M:TMemoryBasicInformation;beginfor?i:=Application.ComponentCount-1?downto?0?dobeginVirtualQuery(GetClass(Application.Components[i].ClassName),M,SizeOf(M));if?(ModuleInstance=0)?or?(HMODULE(M.AllocationBase)=ModuleInstance)?thenApplication.Components[i].Free;end;//下面這兩個(gè)函數(shù)應(yīng)該是只要取其中一個(gè)呼叫即可UnRegisterModuleClasses(ModuleInstance);//直接注銷PackageUnloadPackage(ModuleInstance);//間接注銷,呼叫Package中的finalization區(qū)段end;?
?
-
完整的Package項(xiàng)目架構(gòu)范例
| 子系統(tǒng)名稱 | 內(nèi)部主要對(duì)象 | 補(bǔ)充說明 |
| Project0.exe(MIS主系統(tǒng)) | Form0(Unit0.pas) | 整個(gè)項(xiàng)目中唯一的EXE文件Project的Option選項(xiàng)要設(shè) ■Builderwithruntimepackages并加入BaseForm,MySub兩個(gè)DCP (靜態(tài)連結(jié)) |
| Package1.bpl(會(huì)計(jì)子系統(tǒng)) | Form1(Unit1.pas) | Requires區(qū)段要加入 BaseForm,MySub兩個(gè)DCP (靜態(tài)連結(jié)) |
| Package2.bpl(人事子系統(tǒng)) | Form2(Unit2.pas) | Requires區(qū)段要加入 BaseForm,MySub兩個(gè)DCP (靜態(tài)連結(jié)) |
| Package3.bpl(庫存子系統(tǒng)) | Form3(Unit3.pas) | Requires區(qū)段要加入 BaseForm,MySub兩個(gè)DCP (靜態(tài)連結(jié)) |
| MySub.bpl共享函數(shù)庫 | 無,只有函數(shù)程序代碼 MySub2003.pas | 并提供MySub.dcp供其它系統(tǒng)靜態(tài)連結(jié)之用 |
| BaseForm.bpl共享繼承Form雛形 | FormBase (UnitFormBase.pas) | 并提供BaseForm.dcp供其它系統(tǒng)靜態(tài)連結(jié)之用 |
注:在此仍不厭其煩的提醒:每個(gè)Package的Source最后都要在end.之前插入注冊(cè)(RegisterClass)/注銷(UnRegisterClass)自己類別的程序代碼
?
-
Project0.exe(MIS主系統(tǒng))
注:不管這個(gè)唯一的EXE主程序是否需要加入自訂的共享模塊(如本例的BaseForm,MySub兩個(gè)DCP),沒有的話,它仍然要將Builder with runtime packages打勾(就算只有使用那些系統(tǒng)內(nèi)定的VCL、DCP),否則這個(gè)EXE文件執(zhí)行后會(huì)無法動(dòng)態(tài)加載其它的子系統(tǒng)模塊,會(huì)出現(xiàn)找不到類別的錯(cuò)誤,這個(gè)問題我花了一整個(gè)下午才找到問題原來在這里;但我不知原因是否為Delphi Bug;因?yàn)樵谖业恼J(rèn)知,若不使用自訂的共享模塊(有的話也是放到靜態(tài)鏈接中),主程式跟其它的子系統(tǒng)間則只有動(dòng)態(tài)加載的關(guān)系,那靜態(tài)鏈接則只有決定是否要將系統(tǒng)的VCL靜態(tài)鏈接進(jìn)來的問題;Builder with runtime packages打不打勾,單純也只決定跟系統(tǒng)VCL間的關(guān)系,為何會(huì)影響其它子系統(tǒng)的動(dòng)態(tài)加載??我不愿就看圖說故事或湊答案的方式來牽強(qiáng)解釋這個(gè)問題原因….只有推論為Delphi bug
- Package1.bpl(會(huì)計(jì)子系統(tǒng))
- Package2.bpl(人事子系統(tǒng))
- Package3.bpl(庫存子系統(tǒng))
(略,以上類推)
注:
1.在Requires區(qū)段(靜態(tài)連結(jié))中,除了手動(dòng)加入的BaseForm,MySub兩個(gè)DCP外,其它DCP是由系統(tǒng)自動(dòng)加入的,不用理會(huì)它
2.Package的Contains區(qū)段中,彼此間不能有相同名稱的Unit,也就是說Package2中的Unit不能跟Package1中一樣也叫Unit1(要改名如Unit2或其它)
- MySub.bpl共享函數(shù)庫(無Form,只有函數(shù)庫的程序代碼MySub2003.pas)
- BaseForm.bpl共享繼承Form雛形
?
?
- Package項(xiàng)目的測試環(huán)境
Package在測試及除錯(cuò)上由于BPL不能直接執(zhí)行驗(yàn)證結(jié)果,所以在開發(fā)中的測試是個(gè)問題;不過前面說過,除了項(xiàng)目文件架構(gòu)不同外,Source開發(fā)式和一般Project項(xiàng)目是沒什么兩樣的,以前面介紹過的Package1.bpl(會(huì)計(jì)子系統(tǒng))為例,我們來看一下如何開發(fā)及測試
1.建立一標(biāo)準(zhǔn)可編譯成EXE的Project1.dpr項(xiàng)目,加入U(xiǎn)nit1(Form1),將項(xiàng)目寫好后直接編譯為EXE文件測試
2.當(dāng)測試好后沒問題,新開啟一Package項(xiàng)目叫做Package1.dpk,將Contains區(qū)段納入剛才開發(fā)的Project1.dpr項(xiàng)目中的Unit1(Form1);此時(shí)重新編譯,會(huì)計(jì)子系統(tǒng)就變成一個(gè)BPL而不是EXE文件了
3.以后要修改會(huì)計(jì)子系統(tǒng),就利用Project1.dpr項(xiàng)目來編譯成EXE測試,再用Package1.dpk項(xiàng)目來編譯成BPL
?
- Package項(xiàng)目網(wǎng)狀加載問題
在先前介紹的系統(tǒng)中,各個(gè)子系統(tǒng)理應(yīng)由Project0.exe(MIS主系統(tǒng))這個(gè)唯一的EXE文件來切換進(jìn)入或退出各子系統(tǒng)的時(shí)機(jī);但是我們?cè)趯?shí)際的應(yīng)用中,也可能發(fā)生直接由Package1.bpl(會(huì)計(jì)子系統(tǒng))加載(跳到)Package3.bpl(庫存子系統(tǒng))的情況(記得BPL也是可以加載BPL的吧?),整個(gè)系統(tǒng)RUN過一段時(shí)間后,誰加載誰,或誰已被退出,已經(jīng)不是很清楚了,若此時(shí)突然有個(gè)快捷方式直接回主程序中并結(jié)束程序,我們要能保證所有曾經(jīng)被加載的BPL都要被全部完全釋放干凈;如果動(dòng)態(tài)加載其它BPL的LoadPackage()函數(shù)是分散在各子系統(tǒng)中(人人都可以加載其它的BPL),我們?nèi)绾稳ソy(tǒng)一管理那些PackageHandle變量呢(HMODULE)?所以理想的方法是將加載BPL的動(dòng)作統(tǒng)一放在共同函數(shù)庫(如MySub中),主程序或各個(gè)子系統(tǒng)要加載或釋放BPL都透過在共通函數(shù)庫中包裝好的Package載入或釋放函數(shù),該函數(shù)內(nèi)部有List數(shù)組來記錄管理所有的PackageHandle的消長情況;參考資料“DelphiPackage學(xué)習(xí)筆記”及“DelphiPackage無痛使用”中有個(gè)寫好的共享函數(shù)庫,叫做PkgUtils.pas,您可以把它里面的函數(shù)合并到您公司開發(fā)的共享函數(shù)庫中(如MySub中),所有主程序或各個(gè)子系統(tǒng)的Package加載/釋放動(dòng)作都透過這個(gè)公用函數(shù)庫包裝的函數(shù)去執(zhí)行動(dòng)作。
總結(jié)
以上是生活随笔為你收集整理的转:以Delphi Package架构多人开发应用程序环境的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PID LSim PT3这个仿真模块 S
- 下一篇: 1每天Python小例-12306爬虫#