Solved

COM: Typecasting between TObject and Interfaces

Posted on 2000-03-27
7
340 Views
Last Modified: 2010-05-18
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
0
Comment
Question by:Carpathia
  • 3
  • 2
  • 2
7 Comments
 
LVL 20

Accepted Solution

by:
Madshi earned 20 total points
Comment Utility
If you store the interfaces as TObject, the reference count is not incremented. That means, if the TList reference is the only reference to the interface left, then the interface is being deallocated and if you then later typecast ICapPlugIn(TList[0]) this instance is already released. You can do one of two things:

(1) Use a little trick to handle the reference count correctly:

Don't do this:

  YourList.Add(TObject(AnInterface));

But do this:

var obj : TObject;
begin
  ICapPlugIn(obj) := AnInterface;
  YourList.Add(obj);

Now you can use it like this:

  ICapPlugIn(YourList[index]).AMethod;

To release it do this:

var obj : TObject;
begin
  obj := YourList[index];
  YourList.Delete(index);
  ICapPlugIn(obj) := nil;

(2) Use a "real" interface list. I'm not sure, I think Delphi already has something like that. But perhaps D5 only. I'm not sure. If all else fails, you can copy the TList code from the VCL sources and change TObject into IUnknown.

Regards, Madshi.
0
 

Expert Comment

by:vinnair
Comment Utility
After retrieving the object as TObject, you cannot directly typecast it as the interface. You will have to use the following piece of code. The function below takes the index of the element in the TList and then returns the ICapPlugIn interface corresponding to it. Suppose MyList is your TList.

function convert(index: integer): ICapPlugIn;
var
  myobj: TObject;
  myintf: ICapPlugIn;
begin
  myobj := TObject(MyList[index]);
  try
    myobj.GetInterface(ICapPlugIn,myintf);
  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.
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
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).GetInterface.
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

Expert Comment

by:vinnair
Comment Utility
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?
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
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.
0
 

Author Comment

by:Carpathia
Comment Utility
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.



0
 

Author Comment

by:Carpathia
Comment Utility
Problem was solved using Classes.TInterfaceList.
Thanks
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now