How to circumvent codegen error "Initial values of class types can only be used for reading properties."

21 views (last 30 days)
I am writing some logging functionality for my project that involves parallel processing and code generation:
For ease of use, I want to be able to have a logger object 'globally' available throughout my code, so that I do not have to pass logger objects to subfunctions in which I want to create log statements. In order to avoid global variables, I came up with the following structure:
I created a value class "Logger"
classdef Logger
properties(Constant)
FileHandle = PersistentProperty();
end
methods
function obj = Logger()
end
function start(obj, file_name)
file_id = fopen(file_name, 'w');
obj.FileHandle.setValue(file_id);
end
function log(obj, varargin)
fprintf(obj.FileHandle.getValue(), varargin{:});
end
function stop(obj)
fclose(obj.FileHandle.getValue());
end
end
end
which uses handle class "PersistentProperty"
(I do not use setter and getter methods on purpose since this is not compatible with constant properties)
classdef PersistentProperty < handle
properties
Value
end
methods
function setValue(obj, value)
obj.Value = value;
end
function value = getValue(obj)
value = obj.Value;
end
end
end
In my main, I use class Logger as follows:
function main()
logger = Logger(); % create logger object in base workspace
logger.start('main.log');
logger.log('Before parallel loop\n');
sub1();
parfor (idx = 1:2, 2)
par_logger = Logger(); % create logger objects in parallel worker's workspaces
par_logger.start(sprintf('worker%i.log', int8(idx)));
par_logger.log('This is worker %i\n', int8(idx));
sub2();
par_logger.stop();
end
logger.log('After parallel loop\n');
logger.stop();
end
function sub1()
logger = Logger();
logger.log('sub1\n'); % this log statement goes to main.log
end
function sub2()
logger = Logger();
logger.log('sub2\n'); % this log statement goes to worker1.log and worker2.log
end
The code above creates three log files. One in the base workspace (main.log) and one for each parallel workspace (worker1.log, worker2.log). The nice thing is that although functions sub1() and sub2() create their own logger instances, "PersistentProperty" (since it is a handle class) contains the original file handle that it was assigned at the time when logger.start(...) was called. This way the logger objects in sub1() and sub2() 'know' the correct file handle without having to pass it directly via a function argument or without using globals.
The above works perfectly fine when I run it in a Matlab console. The content of the log files is as expected
main.log
Before parallel loop
sub1
After parallel loop
worker1.log
This is worker 1
sub2
worker2.log
This is worker 2
sub2
However, when I try to generate code from it, I get the error message
Initial values of class types can only be used for reading properties.
I understand that, in this case, codegen has a limitation that only allows reading properties of class "PersistentProperty".
  1. Is there a way to work around this limitation? Maybe there is some detail that I am missing.
  2. Do I need to change my structure completely? Any suggestions for a good alternative way?
  1 Comment
Tony Mohan Varghese
Tony Mohan Varghese on 28 Jun 2022
To reproduce the error can you please specify the verison of MATLAB and the also paste the codegen command that you are using the generate the code?

Sign in to comment.

Answers (0)

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!