如何在 Delphi 中将接口强制转换为对象

6fe3ivhb  于 2022-12-23  发布在  其他
关注(0)|答案(6)|浏览(209)

在 Delphi 中,我有一个对IInterface的引用,我想将它强制转换为底层TObject
使用TObject(IInterface)显然不能在 Delphi 中工作(尽管它应该能在Delphi2010中工作)
我的搜索引导我到a function that should do the trick,但它对我不起作用,当我试图调用返回对象上的方法时,我得到了AV。
我不能真正修改类,我知道这会破坏OOP

5fjcxozz

5fjcxozz1#

除了依赖 Delphi 的内部对象布局,你还可以让你的对象实现另一个接口,它只会返回对象。当然,这只有在你可以访问对象的源代码时才有效,但如果你没有访问对象的源代码,你甚至不应该使用这些技巧。

interface 

type
  IGetObject = interface
    function GetObject: TObject;
  end;

  TSomeClass = class(TInterfacedObject, IGetObject)
  public
    function GetObject: TObject;
  end;

implementation

function TSomeClass.GetObject: TObject;
begin
  Result := Self;
end;
wqsoz72f

wqsoz72f2#

你是对的。从 Delphi 2010开始,你可以使用as操作符,例如通过aObject := aInterface as TObject甚至aObject := TObject(aInterface)
这个as操作符使用一个特殊的隐藏接口GUID(ObjCastGUID)来检索对象示例,调用TObject.GetInterface的增强版本,该版本在 Delphi 2010之前不存在。请参阅System.pas单元的源代码来了解它是如何工作的。
我已经发布了一些适用于 Delphi 到XE2的代码,包括Delphi2009。
参见http://blog.synopse.info?post/2012/06/13/Retrieve-the-object-instance-from-an-interface

vu8f3i0k

vu8f3i0k3#

当您知道实现对象是TComponent后代时,还有一个不错的替代方法。
您可以使用IInterfaceComponentReference接口,该接口以Classes为单位定义:

IInterfaceComponentReference = interface
  ['{E28B1858-EC86-4559-8FCD-6B4F824151ED}']
  function GetComponent: TComponent;
end;

然后在TComponent中声明(并实现为返回self):

TComponent = class(TPersistent, IInterface, IInterfaceComponentReference)

因此,如果您知道实现对象是TComponent,则可以执行以下操作:

function InterfaceToComponent(const AInterface: IInterface): TComponent;
var
  vReference: IInterfaceComponentReference;
begin
  if Supports(AInterface, IInterfaceComponentReference, vReference) then
    result := vReference.GetComponent
  else
    result := nil;
end;
w8rqjzmb

w8rqjzmb4#

简而言之:你不应该或者添加一个带有为你返回指针的方法的接口,否则就是黑客行为。
注意,接口“示例”可以用另一种语言实现(它们是COM兼容的)和/或可以是进程外的东西的存根等。
总而言之:接口示例只同意接口,不同意其他任何东西,当然不能实现为 Delphi 示例

w8f9ii69

w8f9ii695#

Hallvard的破解是针对 Delphi 编译器如何生成代码的。这在过去非常稳定,但听起来他们在Delphi 2009中做了一些重大的改变。我这里只安装了2007,在那里,Hallvard的代码工作得很好。
GetImplementingObject是否返回NIL?
如果是这样,那么如果您在GetImplementingObject例程中调试并设置case语句的断点,那么QueryInterfaceThunk.AddDirective的值在调试器中计算为什么?

58wvjzkj

58wvjzkj6#

var
  N, F: NativeInt; // NativeInt is Integer(in delphi 32bit ) 
  S: TObject;
begin
  N := NativeInt(Args[0].AsInterface) - 12; 
  {subtract 12 byte to get object address(in x86 ,1 interface on class) }
  S := TObject(N);    
  writeln(S.ToString);

end;

相关问题