我正在將 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”,但這沒有任何區別。
如何讓這個作業?
謝謝!
uj5u.com熱心網友回復:
由于以下原因,該is運算子不能跨 BPL (DLL) 作業:
- 您正在檢查的類在其自己的單元檔案中實作。
- 您構建 BPL,鏈接單元,然后在 BPL 檔案中創建一個 RTTI 部分。
- 然后,您構建 EXE,鏈接單元,并在 EXE 檔案中創建一個新的RTTI 部分。
現在:這兩個模塊是相同的,但是運算子用來檢查相等性class name的 RTTI不同,所以運算子回傳FALSE!is
解決方案:檢查類名是否相等。
uj5u.com熱心網友回復:
我在某個地方找到了這個,但它似乎與 Antionio 的回答有點矛盾。
當您使用包時,記憶體中的任何單元都只有一個副本。Forms 一份,SysUtils 一份,System 一份(嗯,大部分),StdCtrls 一份等。所有與類相關的操作,例如“is”和“as”運算子,都依賴于類參考。類參考實際上只是地址。它們指向類內部布局的定義。(它們指向所謂的虛擬方法表,即 VMT。)如果兩個類指向同一個 VMT——如果地址相等,則它們是相同的。當您在 EXE 的 StdCtrls 副本中定義了一個類,而在 DLL 的 StdCtrls 副本中定義了相同的類時,這些類將真正具有不同的地址。“is”和“as”運算子不適用于跨模塊類。但是當你使用包時,
uj5u.com熱心網友回復:
正如 Antonio Petricca 所寫(謝謝!),不可能使用is運算子。我現在已經通過比較(祖先)類名來實作這一點 - 我想分享代碼:
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;
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/503933.html
標籤:德尔福 rtti delphi-11-亚历山大 bpl
