How to cast a Interface to a Object in Delphi
Solution 1
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;
Solution 2
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
Solution 3
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;
Solution 4
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
Solution 5
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?
Yona
Updated on June 05, 2022Comments
-
Yona almost 2 years
In delphi 2009 I have a reference to a
IInterface
which I want to cast to the underlyingTObject
Using
TObject(IInterface)
obviously doesn't work in Delphi 2009 (it's supposed to work in Delphi 2010 though)My searches lead me to a function that should do the trick, but it doesn't work for me, I get AV's when I try to call methods on the returned object.
I can't really modify the Classes and I know that this breaks OOP