我正在尝试编写一个围绕 serial
端口读取传感器的类:
classdef sensor < handle
properties
Value
s
end
methods
function obj = sensor(port)
obj.s = serial(port);
obj.s.BytesAvailableFcn = @(o,e) obj.getData;
fopen(obj.s);
end
function delete(obj)
disp('called destructor');
try
fclose(obj.s);
delete(obj.s);
end
end
function getData(obj)
obj.Value = fscanf(obj.s, '%d');
end
end
end
当我尝试清除工作区时,从未调用析构函数:
>> foo = sensor('COM1');
>> clear foo % should disp() something!
基于我的 previous experiences ,仍然必须有对 foo
的引用。原来这是嵌入在串行端口 foo.s
中:
>> ports = instrfindall;
>> ports.BytesAvailableFcn
ans =
@(o,e)obj.getData
一旦我清除了 BytesAvailableFcn
,即
>> ports.BytesAvailableFcn = '';
然后 clear all
,我显示了我的调用的析构函数
。
我怎样才能打破这个循环引用并让我的析构函数被调用?如果未调用析构函数,串行端口将保持绑定(bind)状态。
最佳答案
问题不完全在于你有一个循环引用;理论上,MATLAB 应该捕捉到这些。问题是循环引用通过 Java 进行,而 MATLAB 无法捕获它。
更详细地说 - 您的 serial
对象在内部包含一个 Java 对象,它是捕获到串行端口连接的真实对象。当您设置其回调时,MATLAB 会设置底层 Java 对象的回调。如果回调是针对包含串行对象作为属性的对象的方法,那么您就有了一个通过底层 Java 对象的循环引用。当您调用 clear
时,MATLAB 会检查循环引用,如果它们都在 MATLAB 中,它会捕获它们并调用析构函数 - 但它不会在通过 Java 时捕获它们。
一种解决方案是显式调用析构函数,也许这不会太麻烦。
另一种解决方法可能是简单地不将回调作为类的方法 - 也许它可以只是一个常规函数,因为它似乎不需要任何信息来自主对象本身而不是对串行对象的引用。如果您希望将所有代码保存在一个文件中,也许您可以将其创建为匿名函数(但要小心,因为匿名函数将捕获它创建的工作空间,这取决于您创建它的位置可能包括对主对象的引用,在这种情况下,您将再次获得循环引用。
编辑:罗迪说得对 - 抱歉,我读问题的速度太快,没有注意到 getData
实际上设置了 Value
属性而不仅仅是返回数据。罗迪在他的回答中的解决方案可能是另一种解决方法,但就像他说的那样 - 讨厌。我只是手动调用 delete
。
关于matlab - 当对象的方法之一用作其自身属性的回调时,如何调用对象的析构函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24189308/