7

Can I save an unknown interface to a pointer ?

For example I have an unknown interface and want to save it to a TreeNode Data?

var
  X : Inknown;

To save :

....  
  Node:=TreeView1.Items.Add;
  //Node.data:=x; //compiler won't allow this
  Node.data:=@x;
...  

To get :

...  
var
  //X:=Node.data; //compiler won't allow this too
  Pointer(X):=Node.data; //an exception caught
...  
bummi
  • 27,123
  • 14
  • 62
  • 101
Theo
  • 454
  • 1
  • 7
  • 21

2 Answers2

13

An interface is a pointer, so you can store it as-is (don't use the @ operator). However, to ensure the interface's lifetime, you have to increment/decrement its reference count manually for as long as the node refers to it, eg:

Node := TreeView1.Items.Add;
Node.Data := Pointer(x);
x._AddRef;

x := IUnknown(Node.Data);

procedure TMyForm.TreeView1Deletion(Sender: TObject; Node: TTreeNode);
begin
   IUnknown(Node.Data)._Release;
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
6

You need to capture the value of the interface reference rather than the address of the variable that holds the reference.

So, do it like this:

Node.Data := Pointer(X);
....
X := IInterface(Node.Data); 
// use IInterface in preference to IUnknown

But you must make sure that you handle the reference counting properly since this cast subverts automatic reference counting.

So, take a reference when you put the interface into the Node:

Node.Data := Pointer(X);
X._AddRef;

and call _Release whenever you modify Node.Data, or destroy the node.


This is rather messy, and easy to get wrong, as you found out. A better way to solve the problem is to let the compiler do the work. Define a sub-class of TTreeNode, and make your tree view use that sub-class. Ignore the Data property of the node and use your own property of type IInterface, introduced in the sub-class.

The way to make this happen is to supply an OnCreateNodeClass event handler that tells the tree view control to create nodes of your sub-class rather than plain old TTreeNode. And example of that technique can be found here: https://stackoverflow.com/a/25611921/

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thanks David. Your suggestion better while using Treeview on UI for displaying purpose. In my case actually i'm using a kind of Virtual Treeview working on background just for init the node (all works in a single procedure). – Theo Dec 28 '13 at 00:07