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

时间:2010-11-09 20:24:10

标签: delphi interface casting delphi-2009 pascal

在delphi 2009中,我引用了IInterface,我想将其转换为基础TObject

使用TObject(IInterface)显然在Delphi 2009中不起作用(它应该在Delphi 2010中工作)

我的搜索引导我a function that should do the trick,但它对我不起作用,当我尝试在返回的对象上调用方法时,我得到了AV。

我无法真正修改类,我知道这会破坏OOP

6 个答案:

答案 0 :(得分:18)

您可以让对象实现另一个简单地返回对象的接口,而不是依赖于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;

答案 1 :(得分:16)

你是对的。从Delphi 2010开始,您可以使用as运算符,例如通过aObject := aInterface as TObject甚至是aObject := TObject(aInterface)

as运算符使用特殊的隐藏接口GUID(ObjCastGUID)来检索对象实例,调用TObject.GetInterface的增强版本,该版本在Delphi 2010之前不存在。请参阅System.pas单位的源代码,以了解其工作原理。

我已经发布了一些适用于Delphi 6的代码,直到XE2,including Delphi 2009

请参阅http://blog.synopse.info/post/2012/06/13/Retrieve-the-object-instance-from-an-interface

答案 2 :(得分:3)

简而言之:您不应该添加具有为您返回指针的方法的接口。其他任何东西都是hackery。

请注意,接口“实例”可以用另一种语言实现(它们是COM兼容的)和/或可能是用于进程外等的存根。

总而言之:接口实例只同意接口而没有别的,当然不是作为Delphi TObject实例实现的

答案 3 :(得分:3)

当您知道实现对象是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;

答案 4 :(得分:2)

Hallvard的hack特别针对Delphi编译器如何生成代码。这在过去一直非常稳定,但听起来他们在Delphi 2009中改变了一些重要的东西。我只在这里安装了2007,并且在那里,Hallvard的代码工作正常。

GetImplementingObject是否返回NIL?

如果是这样,那么如果在GetImplementingObject例程中对case语句进行调试并设置断点,那么QueryInterfaceThunk.AddInstruction的值在调试器中的值是多少?

答案 5 :(得分:-1)

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;