首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 包機制深度解析(二):BPL 運行時行為、依賴解析與自動加載機制

     編輯:Delphi

實驗驅動理解包機制

本文通過構建一個包含 EXE、兩個包的 Project Group,通過修改 contains/requires、運行時包列表、觀察模塊加載情況,實證包的編譯鏈接規則與運行時自動加載邏輯。

實驗結構

// EXE 主程序
program ProjectEXE;
uses Forms, Windows, UnitFormMain in 'UnitFormMain.pas' {FormMain};
{$R *.res}
begin Application.Initialize; Application.CreateForm(TFormMain, FormMain); Application.Run; end.

// 包 Package1: 包含基類 FormAnother 和派生類 Form1
package Package1;
requires vcl, rtl;
contains UnitFormAnother in 'UnitFormAnother.pas' {FormAnother}, UnitForm1 in 'UnitForm1.pas' {Form1};
end.

// 包 Package2: 包含派生類 Form2,依賴 Package1
package Package2;
requires rtl, vcl; // 或 requires Package1
contains UnitForm2 in 'UnitForm2.pas' {Form2};
end.

核心發現

1. 編譯單元集合運算:最終 EXE/BPL 包含 B - A

  • 集合 A:從運行時包列表(或 requires)出發,遞歸獲取所有依賴包中包含的單元集合。
  • 集合 B:從 EXE/DPK 的 uses/contains 出發,遞歸獲取項目直接引用的單元集合。
  • 結果:目標文件(EXE 或 BPL)僅包含 B - A(即 B 中不屬於 A 的單元)。屬於 A 的單元由運行時包提供,無需鏈接 DCU。

驗證:Package1 僅 contains Form1(隱式引用 FormAnother),編譯警告「隱式引入 UnitFormAnother」。最終 Package1.bpl 確包含三個單元。EXE 勾選 Package1 後,EXE 僅含 FormMain,Form1/FormAnother 在 Package1.bpl 中。

2. 依賴傳遞與單元去重

  • Package2 requires Package1 時,Package2.bpl 僅含 Form2(FormAnother 來自 Package1)。
  • Package2 requires vcl, rtl 不依賴 Package1 時,Package2.bpl 含 Form2 + FormAnother(雙份副本)。
  • 鐵律:若 EXE 同時使用兩個包含相同單元(如 FormAnother)的包,編譯報錯「重複單元」。運行時也會困惑:實例化該類時調用哪個包?

3. 自動加載規則:A ∩ B ≠ ∅ 的包會被自動加載

實驗:EXE uses Form1,Package2 contains Form2 requires Package1,EXE 僅勾選 Package2。運行時模塊窗口顯示:rtl、vcl、Package1 被加載,Package2 未加載!

規則:Delphi 自動加載集合 A 中與集合 B 有交集的包。Package2 雖在列表中,但其單元 Form2 未被 EXE 直接引用(EXE 引用 Form1),故 Package2 不自動加載。Package1 包含 Form1(屬於 B),故自動加載。

4. 手動加載前提:完全脫耦

要實現完全手動 LoadPackage,包必須:

  • 不在任何 requires 鏈中(直接/間接)。
  • 包含的單元不在任何 uses/contains 鏈中。
  • 即:調用者編譯時完全不知曉被調包的存在。

項目組編譯順序技巧

Delphi 按 .bpg 列表順序編譯。若被依賴項在下方,會報「找不到文件」。解決:用文本編輯器調整 .bpg 中項目順序,將基礎包置前。

總結

包機制的核心是集合運算與依賴傳遞。編譯期通過「B - A」實現單元去重與動態鏈接;運行期通過「A ∩ B」決定自動加載。掌握這兩條規則,即可精準控制包的劃分、依賴與加載行為,避免「隱式引入」警告與「重複單元」錯誤。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved