Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 如何将未知接口保存到指针?_Delphi_Pointers_Interface - Fatal编程技术网

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

Delphi 如何将未知接口保存到指针?,delphi,pointers,interface,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 Pointe

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

例如,我有一个未知的接口,想将其保存到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
...  

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

那么,这样做:

Node.Data := Pointer(X);
....
X := IInterface(Node.Data); 
// use IInterface in preference to IUnknown
但您必须确保正确处理引用计数,因为此强制转换会破坏自动引用计数

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

Node.Data := Pointer(X);
X._AddRef;
并在修改节点数据或销毁节点时调用
\u Release


正如您所发现的,这相当混乱,而且很容易出错。解决这个问题的更好方法是让编译器来完成这项工作。定义一个子类
TTreeNode
,并使树视图使用该子类。忽略节点的数据属性,并使用子类中引入的自己的
IInterface
类型的属性


实现这一点的方法是提供一个事件处理程序,它告诉树视图控件创建子类的节点,而不是简单的老式
TTreeNode
。这种技术的例子可以在这里找到:

接口是指针,所以可以按原样存储它(不要使用
@
操作符)。但是,为了确保接口的生存期,只要节点引用它,就必须手动增加/减少其引用计数,例如:

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


如果数据被修改,还需要调用“发布”。@Remy Lebeau:非常感谢。虽然我看得太高了,但很简单。谢谢大卫。在UI上使用Treeview进行显示时,您的建议会更好。在我的例子中,实际上我正在使用一种虚拟树视图在后台工作,只用于初始化节点(所有工作都在一个过程中)。
x := IUnknown(Node.Data);
procedure TMyForm.TreeView1Deletion(Sender: TObject; Node: TTreeNode);
begin
   IUnknown(Node.Data)._Release;
end;