How to call an object's destructor when one of its methods is used as a callback for its own property?

I am trying to write a class that wraps around a port serialfor reading a sensor:

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

When I try to clear the workspace, the destructor is never called:

>> foo = sensor('COM1');
>> clear foo % should disp() something!

Based on previous experience , there should still be a link to foo. It turns out this is built into the serial port foo.s:

>> ports = instrfindall;
>> ports.BytesAvailableFcn
ans = 
    @(o,e)obj.getData

As soon as I delete BytesAvailableFcn, i.e.

>> ports.BytesAvailableFcn = '';

and then clear all, I get displayed called destructor.

How can I break this circular link and call the destructor? If the destructor is not called, the serial port remains connected.

+4
2

, ; MATLAB . , Java, MATLAB .

- serial Java , , . , MATLAB Java. , , , Java. clear, MATLAB , MATLAB, , , Java.

, , , , .

- , , - , . , , ( , , , , , , .

: Rody right - , , getData Value, . , , , - . delete .

+2

!:)

, .

  • . , obj. ( Static, ).
  • . , .
  • Value, , , , Value,

, ( , ), , - , , . , :

classdef sensor < handle

    properties
        s
    end        
    properties (Dependent)
        Value
    end

    methods

        function obj = sensor(port)
            obj.s = serial(port);

            % You cannot use function handle without implicitly passing obj into 
            % it. Instead, get a function handle from another function, one that 
            % does not have this problem:
            obj.s.BytesAvailableFcn = sensor.getGetData(obj.s);                

            fopen(obj.s);
        end

        function delete(obj)
            disp('called destructor');
            try %#ok<TRYNC>
                fclose(obj.s);
                delete(obj.s);
            end
        end

        % Use a getter for Value, so that whenever you query the Value property, 
        % you get the most recently read sensor data
        function V = get.Value(obj) %#ok<MANU>
            V = getData();
        end

    end

    % Use indirection to a Static method, to avoid referencing obj implicitly
    methods (Access = private, Static)
        function f = getGetData(S)
            f = @(o,e)getData(S);
        end
    end

end

% The actual sensor reader 
function data = getData(S)

    persistent port
    if nargin == 1
        port = S; return; end

    try 
        data = fscanf(port, '%d');
    catch ME
        % ...
    end

end

.... .

+1

Source: https://habr.com/ru/post/1544361/


All Articles