How to cast a Interface to a Object in Delphi

前端 未结 6 1015
南旧
南旧 2020-12-01 18:39

In delphi 2009 I have a reference to a IInterface which I want to cast to the underlying TObject

Using TObject(IInterface) obv

相关标签:
6条回答
  • 2020-12-01 19:07

    You are right. Beginning with Delphi 2010, you are able to use the as operator, e.g. via aObject := aInterface as TObject or even aObject := TObject(aInterface).

    This as operator use a special hidden interface GUID (ObjCastGUID) to retrieve the object instance, calling an enhanced version of TObject.GetInterface, which does not exist prior to Delphi 2010. See source code of System.pas unit to see how it works.

    I've published some code working for Delphi 6 up to XE2, including Delphi 2009.

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

    0 讨论(0)
  • 2020-12-01 19:07

    There is a nice alternative when you know the implementing object is a TComponent descendant.

    You can use the IInterfaceComponentReference interface, which is defined up in Classes unit:

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

    And then it's declared in TComponent (and implemented to return self):

      TComponent = class(TPersistent, IInterface, IInterfaceComponentReference)
    

    So if you know the implementing object is a TComponent then you can do this:

    function InterfaceToComponent(const AInterface: IInterface): TComponent;
    var
      vReference: IInterfaceComponentReference;
    begin
      if Supports(AInterface, IInterfaceComponentReference, vReference) then
        result := vReference.GetComponent
      else
        result := nil;
    end;
    
    0 讨论(0)
  • 2020-12-01 19:08

    Hallvard's hack is very specific to how the Delphi compiler generates code. That has been remarkably stable in the past, but it sounds like they changed something significant in Delphi 2009. I only have 2007 installed here, and in that, Hallvard's code works fine.

    Does GetImplementingObject return NIL?

    If so, then if you debug and set a break-point on the case statement in the GetImplementingObject routine, what does the value of QueryInterfaceThunk.AddInstruction evaluate to in the debugger?

    0 讨论(0)
  • 2020-12-01 19:11
    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;
    
    0 讨论(0)
  • 2020-12-01 19:16

    In short: you shouldn't or add an interface with a method that returns the pointer for you. Anything else is hackery.

    Note that an interface "instance" may be implemented in another language (they are COM compatible) and / or may be a stub for something out of process etc etc.

    All in all: an interface instance only agrees to the interface and nothing else, certainly not being implemented as a Delphi TObject instance

    0 讨论(0)
  • 2020-12-01 19:20

    Instead of relying on Delphi's internal object layout you could also have your objects implement another interface which would simply return the object. This, of course, only works if you have access to the source code of the objects to begin with, but you probably shouldn't even use these hacks if you don't have access the source code of the objects.

    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;
    
    0 讨论(0)
提交回复
热议问题