我正在将 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;
我已经考虑过比较类名,但这对后代不起作用。我们尝试过切换项目选项,如“发出运行时类型信息”,但这没有任何区别。
如何让这个工作?
谢谢你,谢谢你
3条答案
按热度按时间qybjjes11#
is
运算符不能跨BPL(DLL)使用,原因如下:现在:两个模块的
class name
相同,但is
运算符用于检查相等性的RTTI不同,因此运算符返回FALSE!**解决方案:**检查类名是否相等。
ct3nt3jp2#
我在某个地方找到了这个,但它似乎与安东尼奥的回答有点矛盾。
当你使用软件包时,任何单元在内存中只有一个拷贝。一个Forms拷贝,一个SysUtils拷贝,一个System拷贝(大部分)、StdCtrls的一个副本等。所有与类相关的操作(如“is”和“as”操作符)依赖于类引用。类引用实际上只是地址。它们指向类内部布局的定义。(它们指向所谓的虚拟方法表VMT。)如果两个类指向相同的VMT --如果地址相等--则它们是相同的。当您在StdCtrls的EXE副本中定义了一个类,而在StdCtrls的DLL副本中定义了同一个类时,这些类实际上会有不同的地址。“is”和“as”操作符不适用于跨模块的类。但是当你使用包时,只有一个类的副本,保存在vcl70.bpl中,因此引用该包的所有模块将共享一个类定义。
kokeuurv3#
正如Antonio Petricca所写的(谢谢!),不可能使用
is
操作符。现在我通过比较(祖先)类名实现了这个操作--我想分享代码:这样,我就可以按如下方式进行检查: