如何将未知接口保存到指针?

时间:2013-12-26 23:09:40

标签: delphi pointers interface

我可以将未知接口保存到指针吗?

例如,我有一个未知的接口,并希望将其保存到TreeNode数据?

var
  X : Inknown;

保存:

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

获得:

...  
var
  //X:=Node.data; //compiler won't allow this too
  Pointer(X):=Node.data; //an exception caught
...  

2 个答案:

答案 0 :(得分:12)

接口是指针,因此您可以按原样存储它(不要使用@运算符)。但是,为了确保接口的生命周期,只要节点引用​​它,就必须手动递增/递减其引用计数,例如:

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;

答案 1 :(得分:6)

您需要捕获接口引用的值,而不是保存引用的变量的地址。

所以,这样做:

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

但是你必须确保正确处理引用计数,因为这个转换会破坏自动引用计数。

因此,在将接口放入节点时请参考:

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

并在修改_Release时调用Node.Data,或销毁节点。


这是相当混乱的,容易出错,正如你发现的那样。解决问题的更好方法是让编译器完成工作。定义TTreeNode的子类,并使树视图使用该子类。忽略节点的Data属性,并使用您在子类中引入的类型为IInterface的属性。

实现这一目标的方法是提供一个OnCreateNodeClass事件处理程序,该处理程序告诉树视图控件创建子类的节点而不是普通的TTreeNode节点。可以在此处找到该技术的示例:https://stackoverflow.com/a/25611921/