![](/img/trans.png)
[英]Compile Delphi component package (bpl) for different Delphi versions
[英]Component is specific class - does not work in BPL structure
我正在將 Delphi 軟件從 Delphi 6 (2001) 升級到 Delphi 11 Alexandria。
該軟件包含許多 BPL,但此代碼無法正常工作。 當檢查來自 BPL 的組件是否是 TIBQuery 時, is 命令沒有返回 True,盡管它確實是。
procedure LoadDLLAndPassDatabaseConnection(const DLLName: string);
var
PackageHandle: HMODULE;
ServiceModule: TMyServiceModule;
I: Integer;
Component: TComponent;
begin
PackageHandle := LoadPackage(PChar(DLLName));
ServiceModule := TMyServiceModule(GetProcAddress(hInst,'GetServiceModule'));
if Assigned(ServiceModule) then
begin
for I:=0 to ServiceModule.ComponentCount - 1 do
begin
Component := ServiceModule.Components[I];
// This component is declared in another bpl.
// It really is an TIBQuery, but the following if never returns True...
// (Evaluating Component.ClassName results in 'TIBQuery')
if Component is TIBQuery then
begin
// this is never executed...
TIBQuery(Component).Database := GetDatabase;
end;
end;
end;
end;
我已經考慮過比較類名,但這不適用於后代。 我們嘗試切換項目選項,例如“Emit runtime type information”,但這沒有任何區別。
如何讓這個工作?
謝謝!
is
運算符不能跨 BPL (DLL) 工作,原因如下:
現在:兩個模塊的class name
相同,但是is
運算符用於檢查相等性的 RTTI不同,因此運算符返回FALSE !
解決方案:檢查 class 名稱是否相等。
正如 Antonio Petricca 所寫(謝謝),不可能使用is
運算符。 我現在通過比較(后代)class 名稱來實現這一點 - 我想分享代碼:
function IsSameClassOrAncestor(const ClazzToCheck: TClass; const Clazz: TClass): Boolean;
begin
Result := SameText(ClazzToCheck.ClassName, Clazz.ClassName);
if not Result and not SameText(ClazzToCheck.ClassName, 'TObject') then
begin
Result := IsSameClassOrAncestor(ClazzToCheck.ClassParent, Clazz);
end;
end;
這樣,我可以檢查如下:
if IsSameClassOrAncestor(Component, TIBQuery)
begin
// The code is now executed correctly, also for descendants
TIBQuery(Component).Database := GetDatabase;
end;
我在某個地方找到了這個,但它似乎與 Antionio 的回答有點矛盾。
使用包時,memory 中的任何單元都只有一個副本。 Forms 一份,SysUtils 一份,System 一份(嗯,大部分),StdCtrls 一份等。所有與類相關的操作,例如“is”和“as”運算符,都依賴於 class參考。 Class 引用實際上只是地址。 它們指向類內部布局的定義。 (它們指向所謂的虛擬方法表,即 VMT。)如果兩個類指向同一個 VMT——如果地址相等,則它們是相同的。 當您在 EXE 的 StdCtrls 副本中定義了 class 並且在 DLL 的 StdCtrls 副本中定義了相同的 class 時,這些類實際上將具有不同的地址。 “is”和“as”運算符不適用於跨模塊類。 但是,當您使用包時,只有一份 class 副本保存在 vcl70.bpl 中,因此所有引用該 package 的模塊將共享一個 class 定義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.