Accessing struct by variable in Code Generation

Hello,
I am trying to use code generator to accelerate a text reader for my research. I am currently stuck at the following lines.
curLine = fgetl(fid);
atts = strsplit_c(curLine,' ');
for m = 3:length(atts)
data.(atts{m}) = zeros(real(data.numAtoms),1);
end
The error occures at "data.(atts{m}) = zeros(real(data.numAtoms),1);" with the error "Non-constant expression or empty matrix. This expression must be constant because its value determines the size or class of some expression".
strsplit_c is my implementation of strsplit that is code generation happy. If this may be the location of the error I will be happy to post that code.
I have a second error where I try to place values in the structure.
line = fgetl(fid);
lineVal = eval_c(line,' ');
% lineVal = eval(['[',line,']']);
for m = 3:length(atts)
data.(atts{m})(k) = lineVal(m-2); % <- This is where the error is...
end

Answers (1)

I suspect that your first problem is not the dynamic field name, but rather the dynamic size of the array being generated. MATLAB needs to know the size because it needs to generate the array on the stack, and it needs to be sure that it is not going to overrun the allocated stack space.
The work-around is to use coder.varsize https://www.mathworks.com/help/coder/ref/coder.varsize.html
This allows variables to be allocated on the heap instead of on the stack.
I think you might still have problems with dynamic field names, but you could test that part out separately by experimenting with assigning something of constant size instead of dynamic size.

9 Comments

I got rid of the first error by defining my structure a little later with information stored in temp variables.
I can now declare the entire structure completely allocated via
data = struct(var0,n,var1,zeros(n,1),var2,zeros(n,1),...,var3,zeros(n,1))
This fixed the first error but I still get the same second error with the same message.
The only issue now is that I do not know the order in which the fieldnames will be called.
atts{m} will be one of the filednames but I have no way of knowing the order.
I could but I don't know if all of the filednames will be used.
I found that I can do a switch statement and the compiler is happy.
New issue is with the initialization.
I am reading in files from the dir() function
allFiles = dir('myData*.txt');
for k = 1:length(allFiles)
data = myNewMexFunc(allFiles(k));
% Do something with the data
end
The compiler now dosn't like that allFiles(k).name can have different sizes. I can't simply pad as I want to use this function for may different data files. (the star represents a simulation step).
Notice it does not have an Extended Capabilities section. The implication is that it does not support Code Generation
C itself does not have directory operations.
The POSIX standard does have directory operations; see https://docs.rtems.org/branches/master/posix-users/files_and_directory.html . You can use coder.ceval() to force calls to such routines.
Sorry for any confusion
My matlab script calls dir not the function that I want to be converted to c code (myNewMexFunc).
The current issue is that the struct allFiles does not have consistant char array lengths for allFiles(1).name and allFiles(1).folder.
Does the function need anything from the directory information other than the file name? Or other than the file name + folder information? If all it needs are file name or file name + folder, then build fully qualified names and pass those in as a string or as a character vector; you might want to null-terminate first;
Or perhaps even fopen() before calling the function so it never has to deal with character vectors ?
I'll try the fopen and simply pass the fid.
I tried building the entire file name before sending it to the function but was met with the error that the char array changed sizes and you can't use coder.varsize on an input value.
Passing the fid worked.

Sign in to comment.

Products

Release

R2020a

Asked:

on 13 Dec 2020

Commented:

on 15 Dec 2020

Community Treasure Hunt

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

Start Hunting!