How to use Matlab Coder to create object whose property is a container of unknown value classes

6 views (last 30 days)
I am trying to convert a portion of a large program to a MEX file via MATLAB Coder. This code involves a user-defined value class, "World". The "World" class has a property, "objects" which is a cell array of other user-defined value classes ("Cube", "Sphere", "Cylinder", etc), each of which is a sub-class of the "Shape" superclass. The program should allow users to include an arbitrary number of "Shape" objects (upto an upper bound, say 10), in an arbitrary order in their "World". To this end, I created the following function which works fine in MATLAB:
function wrld = create_world(objIndxList)%#codegen
% First create instance of World class. World is a user-defined value class with "objects" property.
% The "objects" property is pre-allocated as a 1x10 cell array for compatability with codegen and hetereogeneous cell arrays.
% Each element of "objects" is initally a dummy sub-class of the user-defined "Shape" superclass
% The purpose of the create_world function is to replace some or all of the dummy sub-class objects with actual sub-class objects (e.g.,
% Cube, Sphere, Cylinder, etc)
wrld = World();
numObj = length(objIndxList); % This is the number of dummy Shape objects to replace
wrld.objCodes(1:numObj) = objIndxList; % Dummy objects have 0 as their code, whereas real objects are > 0
L = coder.const(length(wrld.objects)); % codegen requires const bounds on for loop
for i=1:L
if objIndxList(i) == 1
wrld.objects{i} = Cube();
elseif objIndxList(i) == 2
wrld.objects{i} = Sphere();
elseif objIndxList(i) == 3
wrld.objects{i} = Cylinder();
else
error('Incorrect object code')
end
if i==numObj % break from for loop once non-null objects are exhausted
break
end
end
end
For example, the output called from MATLAB with [1,2,3] as the input looks like the following:
wrld = create_world([1 2 3])
wrld =
World with properties:
objects: {1×10 cell}
objCodes: [1 2 3 0 0 0 0 0 0 0]
where objects{1:3} are 1x1 Cube, 1x1 Sphere, and 1x1 Cylinder, respectively, and objects{4:10} are 1x1 ShapeDummy.
However, using MATLAB Coder, I continuously get "Type name mismatch: ShapeDummy~=Cube", "Type name mismatch: ShapeDummy~=Sphere", "Type name mismatch: ShapeDummy~=Cylinder" errors. I understand that with C++, the type is static. So when I pre-allocate each cell of the "objects" cell array to ShapeDummy, a type mismatch is registered. I am wondering if there is a workaround of any sort for this type of problem, as it seems fairly generic.
Reading the following link: https://www.mathworks.com/help/simulink/ug/homogeneous-vs-heterogeneous-cell-arrays.html, it appears I am obeying all rules to create a heterogeneous cell array, namely fixed size, indexing into it with a constant upper bound.
Does anyone know if I am missing something or there is a workaround here?
  2 Comments
Alexander Bottema
Alexander Bottema on 10 Sep 2020
There are two issues here:
1) MATLAB Coder does not support changing types (dynamically.) Once you've assigned one thing (ShapeDummy) you cannot switch to another (Cube, Sphere Cylinder)
2) MATLAB Coder does not support object dynamic dispatching. In C++ you would likely use virtual methods and class inheritance to achieve the desired implementation. However, MATLAB Coder doesn't support this.
So hetereogenous cell arrays means that the types can vary at each slot, but once you've assigned it one type it cannot change. Heterogenous cell arrays will in C code be implemented with a struct where each field of the structure is representing each cell array slot respectively. For this reason, hetereogeneous cell arrays has the limitation that referring to a particular cell-array slot, it needs to be constant at compile-time. For-loops referring to a cell array slot 'i' are unrolled, to ensure that all cell-array references are constants (otherwise we cannot map it to a particular structure field.)
Homogeneous cell arrays does not have this limitation (i.e. indexing into them can be determined at run-time) but then the underlying base type must be the same.
The only workaround I can think of is not to store the objects directly (in your World class), but just use pure numbers of some sort (use homogeneous cell arrays, structure arrays, etc.) Then you can create some methods that will recreate the proper object from those numbers. For example,
world.isSphere(id) -> true|false
world.getSphere(id) -> Sphere (this would be an actual class)
Joseph Smalley
Joseph Smalley on 21 Sep 2020
Thanks for your response, Alexander. After reading about virtual functions in C++, it indeed appears that I must create "Abstract" classes explicitly in C++ via virtual methods that would exhibit the same behavior as my abstract Shape class created in MATLAB. This way the items of the World class could be determined at runtime rather than compile-time.
I wonder why MATLAB Coder cannot support this type of conversion?

Sign in to comment.

Answers (0)

Categories

Find more on MATLAB Coder in Help Center and File Exchange

Products


Release

R2020a

Community Treasure Hunt

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

Start Hunting!