Work with MATLAB Structure Arrays - MATLAB & Simulink (original) (raw)
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 exampleDeploy 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 temperatures = factory.createArray({ 5 }, { 72, 75, 69, 68, 70 }); matlab::data::TypedArray pressures = factory.createArray({ 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.
TwoTypedArray<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::vectormatlab::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::vectormatlab::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::TypedArrayRefmatlab::data::Struct nestedStruct = outputArray[0][fieldName];
auto nestedStructFieldNamesIterable = nestedStruct.getFieldNames();
std::vectormatlab::data::MATLABFieldIdentifier
nestedStructFieldNames(nestedStructFieldNamesIterable.begin(), nestedStructFieldNamesIterable.end());