Carpathia
asked on
COM: Typecasting between TObject and Interfaces
I have a manager object which holds a list of Interfaces to objects which want notifying of a particular event.
My manager object stores these Interfaces by typecasting them as Objects and dropping them into a TList.
When it comes to retrieving the interfaces, i cant typecast it back to an ICapPlugIn interface.
So, how can I typecast it, or if I cant, how do I store a list of Interfaces ?
Thx
My manager object stores these Interfaces by typecasting them as Objects and dropping them into a TList.
When it comes to retrieving the interfaces, i cant typecast it back to an ICapPlugIn interface.
So, how can I typecast it, or if I cant, how do I store a list of Interfaces ?
Thx
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Hi vinnair, if Carpathia has typecasted the original interface to TObject, we don't have a valid TObject pointer!! We simply have a typecasted ICapPlugIn pointer. That means you can't call TObject(ICapPlugInPointer) .GetInterf ace.
Hi Madshi,
Since ICapPlugIn is an interface, it will be implemented by some object, which will always be a descendent of TObject. Remember all objects are derived from TObject.
If the object Implementing ICapPlugIn was not a descendent of TObject then the typecasting from an ICapPlugIn interface to a TObject would not have been allowed in the first place. No dummy typecasting is allowed. Even if a compile time error is not raised, a run time error will surely be raised.
Any comments?
Since ICapPlugIn is an interface, it will be implemented by some object, which will always be a descendent of TObject. Remember all objects are derived from TObject.
If the object Implementing ICapPlugIn was not a descendent of TObject then the typecasting from an ICapPlugIn interface to a TObject would not have been allowed in the first place. No dummy typecasting is allowed. Even if a compile time error is not raised, a run time error will surely be raised.
Any comments?
Hi vinnair,
you are not allowed to typecast an interface into an object and then use it as an object. That simply doesn't work. You would get a runtime error. You're right, interfaces are implemented by objects, but if you have e.g. an interface ICapPlugIn, this interface can be implemented by TObject1 or by TObject2. How should Delphi know just from the interface pointer, where the implementing object is and which type it has? This logic is simply not supported in interfaces and COM objects. An interface pointer only gives you the addresses of the interface methods. The address of the implementing object is not stored in the interface.
Typecasting is not nice, of course. But it works alright, if you don't use the typecasted pointer as a TObject reference.
Look, you can do this:
var i1 : integer;
p1 : pointer;
begin
i1 := 777;
p1 := pointer(i1);
i1 := integer(p1);
No problem with this code - as long as you don't try to use "p1^". The same is true for interfaces and objects. You can typecast them, but you MUST NOT use the typecasted type as a reference.
you are not allowed to typecast an interface into an object and then use it as an object. That simply doesn't work. You would get a runtime error. You're right, interfaces are implemented by objects, but if you have e.g. an interface ICapPlugIn, this interface can be implemented by TObject1 or by TObject2. How should Delphi know just from the interface pointer, where the implementing object is and which type it has? This logic is simply not supported in interfaces and COM objects. An interface pointer only gives you the addresses of the interface methods. The address of the implementing object is not stored in the interface.
Typecasting is not nice, of course. But it works alright, if you don't use the typecasted pointer as a TObject reference.
Look, you can do this:
var i1 : integer;
p1 : pointer;
begin
i1 := 777;
p1 := pointer(i1);
i1 := integer(p1);
No problem with this code - as long as you don't try to use "p1^". The same is true for interfaces and objects. You can typecast them, but you MUST NOT use the typecasted type as a reference.
ASKER
My problems are solved. I started converting borlands TList to a TInterfaceList, only to find that one already exists in the same unit :)
I've given Madshi the points, for teaching me about the reference count trick, and suggesting modifying TList.
I've given Madshi the points, for teaching me about the reference count trick, and suggesting modifying TList.
ASKER
Problem was solved using Classes.TInterfaceList.
Thanks
Thanks
function convert(index: integer): ICapPlugIn;
var
myobj: TObject;
myintf: ICapPlugIn;
begin
myobj := TObject(MyList[index]);
try
myobj.GetInterface(ICapPlu
except
begin
Showmessage('Interface not supported by class');
exit;
end;
end;
Result := myintf;
end;
The Getinterface function is used to retrieve interface for an object.
This should solve your problem. If not you can get back to me.