Work with MATLAB Structure Arrays
In MATLAB®, you can create struct arrays by dynamically assigning field names and values. In contrast, C++ is a statically typed language that requires all fields of a struct and their types to be declared upfront. This discussion uses the example Deploy MATLAB Function That Accepts Struct Array as Input Argument to explain how to handle MATLAB structs in C++ code.
Struct Input
In MATLAB, struct arrays can be created by dynamically assigning field names and values. C++ being a statically typed language requires all fields of a struct and their types to be declared upfront.
When C++ code calls a MATLAB function that requires a MATLAB struct as input, the struct must be explicitly created in C++ using appropriate data types through the MATLAB Data API. For example:
% MATLAB
data = struct();
data.temperatures = [72, 75, 69, 68, 70];
data.pressures = [30, 29.5, 30.2, 29.9, 30.1]; |
// C++ matlab::data::ArrayFactory factory; matlab::data::TypedArray<double> temperatures = factory.createArray<double>({ 5 }, { 72, 75, 69, 68, 70 }); matlab::data::TypedArray<double> pressures = factory.createArray<double>({ 5 }, { 30, 29.5, 30.2, 29.9, 30.1 }); matlab::data::StructArray inputStruct = factory.createStructArray({ 1 }, { "temperatures", "pressures" }); inputStruct[0]["temperatures"] = temperatures; inputStruct[0]["pressures"] = pressures; |
An
ArrayFactory
object named factory is created. This object is used to create MATLAB data arrays in C++. It's a factory class that provides methods to create various types of MATLAB data arrays.The
matlab::data::TypedArray<T>
class in the MATLAB Data API is a template class designed to represent arrays of a specific type<T>
in C++ code that interact with MATLAB. This class allows C++ programs to create arrays that are compatible with MATLAB data types, facilitating the exchange of data between C++ and MATLAB environments.Two
TypedArray<double>
objects,temperatures
andpressures
, are created using the factory object. Each call tofactory.createArray<double>()
specifies the array dimensions and initializes the array with given values. Here, both arrays are 1-dimensional with5
elements each, representing temperature and pressure data, respectively.A
StructArray
namedinputStruct
is created, again using thefactory
object. ThecreateStructArray
method is called with two arguments:The first specifies the dimensions of the struct array. In this case, a 1x1 struct array.
The second is an initializer list of strings that define the field names of the struct:
"temperatures"
and"pressures"
.
Finally, the fields of the first (and only) struct in
inputStruct
are populated with thetemperatures
andpressures
arrays. The syntaxinputStruct[0]["temperatures"]
accesses the"temperatures"
field of the first struct and assigns the temperatures array to it. Similarly, the"pressures"
field is populated with thepressures
array.
Struct Output
When a MATLAB function called from C++ returns a MATLAB struct, it is returned as a matlab::data::Array
in the C++ code. To retrieve the field names and field values, some processing
is necessary. For example:
// Function to print the MATLAB computation results void printMatlabResults(matlab::data::Array outputArray) { matlab::data::StructArray structArray = outputArray; auto topLevelStructFieldNamesIterable = structArray.getFieldNames(); std::vector<matlab::data::MATLABFieldIdentifier> topLevelStructFieldNames(topLevelStructFieldNamesIterable.begin(), topLevelStructFieldNamesIterable.end()); for (const matlab::data::MATLABFieldIdentifier& fieldName : topLevelStructFieldNames) { std::string outerFieldName(fieldName); std::cout << "Field: " << outerFieldName << std::endl; matlab::data::TypedArrayRef<matlab::data::Struct> nestedStruct = outputArray[0][fieldName]; auto nestedStructFieldNamesIterable = nestedStruct.getFieldNames(); std::vector<matlab::data::MATLABFieldIdentifier> nestedStructFieldNames(nestedStructFieldNamesIterable.begin(), nestedStructFieldNamesIterable.end()); for (const matlab::data::MATLABFieldIdentifier& fieldName : nestedStructFieldNames) { std::string innerFieldName(fieldName); matlab::data::TypedArrayRef<double> fieldValue = nestedStruct[0][fieldName]; double value = fieldValue[0]; std::cout << " " << innerFieldName << ": " << std::fixed << std::setprecision(4) << value << std::endl; } } }
The MATLAB struct returned from the MATLAB function as a
matlab::data::Array
needs to be converted to amatlab::data::StructArray
. Direct access to the struct fields is not available.matlab::data::StructArray structArray = outputArray;
Retrieve the iterable of field names from the struct array.
auto topLevelStructFieldNamesIterable = structArray.getFieldNames(); std::vector<matlab::data::MATLABFieldIdentifier> topLevelStructFieldNames(topLevelStructFieldNamesIterable.begin(), topLevelStructFieldNamesIterable.end());
Use a loop to process each field in the struct. This involves accessing each field by name and processing its contents.
for (const matlab::data::MATLABFieldIdentifier& fieldName : topLevelStructFieldNames) { std::string outerFieldName(fieldName); std::cout << "Field: " << outerFieldName << std::endl; ... }
If the fields themselves contain structs, repeat the process of getting field names and iterating over them.
matlab::data::TypedArrayRef<matlab::data::Struct> nestedStruct = outputArray[0][fieldName]; auto nestedStructFieldNamesIterable = nestedStruct.getFieldNames(); std::vector<matlab::data::MATLABFieldIdentifier> nestedStructFieldNames(nestedStructFieldNamesIterable.begin(), nestedStructFieldNamesIterable.end());