Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get string of enum - matlab coder

I have an enum like this:

classdef(Enumeration) bla_type < int32
    enumeration
        bla_one(1)
        bla_2(2)
    end
end

I can get the 'string representation of an element' like this:

char(bla_type.bla_one)

=>

bla_one

Unfortunately, matlab coder does not like this. Are there any alternatives?

like image 333
cs0815 Avatar asked Feb 10 '13 18:02

cs0815


1 Answers

There's no elegant built-in way in Coder to do this; the enumerated type becomes a standard enum in C, and the enumeration function in MATLAB is unavailable in Coder. The simplest, but unpleasant, way to do it is to create a function with a switch statement with the manually populated string names. It's not nice, since now you have to maintain the names in two places.

However, one way that does work nicely is to use one of the more powerful features of Coder: coder.const.

The solution is to have a function that creates a table of the enumeration members and their values. This function itself cannot be compiled, but rather is called during compilation to build a lookup table in the resulting C code. We can use this lookup table in a Coder compatible function to get the data.

Imagine we have an enumerated type like this (in someenum.m):

classdef someenum < int32 %#codegen
    enumeration
        First_thing (0)
        Second_thing (2)
        Another_thing (3)
        No_thing (4000)
    end
end

We also then have the build-time function called 'buildsomeenum2name.m':

function [namearray, memberidx] = buildsomeenum2name
%BUILDSOMEENUM2NAME Compile-time creation of lookup table for someenum 
% THIS FUNCTION IS NOT CODER COMPATIBLE, BUT IS CALLED DURING COMPILE
% TO CREATE A LOOKUP TABLE.

[members, names]=enumeration('someenum');

maxlen = 0;
for i=1:numel(names)
    maxlen = max(maxlen, numel(names{i}));
end

namearray = char(zeros(numel(names), maxlen));
for i=1:numel(names)
    namearray(i, 1:numel(names{i})) = names{i};
end

memberidx =  int32(members); %#ok<NASGU>

end

When buildsomeenum2name is called in MATLAB, it creates an array of string names of all the members of the enumerated type and another vector list of their numeric values in the same order.

Here's the cool part. MATLAB Coder can evaluate functions at build time and turn them into constants. These constants become literals in the resulting C code, rather than actual code. Since the functions are evaluated at build time, the enumeration information is put into a nice table, therefore if we make a Coder-compatible lookup function, we can use it to convert the member types into a string. We'll call this function 'someenum2name.m':

function name = someenum2name(enum) %#codegen
%SOMEENUM2NAME Get the string name of an enumerated type

% The following line loads namearray and memberidx with constant arrays
coder.extrinsic('buildsomeenum2name');
[namearray, memberidx] = coder.const(@buildsomeenum2name);

% First find the index of the enumerated type in the memberidx vector

index = find(memberidx==int32(enum));
if isempty(index)
    name = 'UNKNOWN';
    return;
end

name = deblank(namearray(index,:));

end

This function uses the coder.const command to evaluate buildsomeenum2name at compile time and create the lookup tables. We have to instruct Coder not to try to compile buildsomeenum2name, so use the coder.extrinsic command to tell it to ignore the function. Then someenum2name can look up the index for the string and pull it out (deblank is used because the strings in the array have trailing 0's that need to be pulled out.) The function someenum2name can be called both within MATLAB and in Coder compiled code.

This method keeps everything in-sync, so if you ever add a new member to the enum or rearrange them, the coder.const function will make sure that the values are rebuilt in the output code so that someenum2name works.

At the command line, this looks like:

>> someenum2name(someenum.No_thing)
ans =
No_thing
like image 190
Tony Avatar answered Oct 20 '22 03:10

Tony