Use Dynamically Allocated C++ Arrays in Generated Function Interfaces - MATLAB & Simulink (original) (raw)
In most cases, when you generate code for a MATLAB® function that accepts or returns an array, there is an array at the interface of the generated C/C++ function. For an array size that is unknown at compile time, or whose bound exceeds a predefined threshold, the memory for the generated array is dynamically allocated on the heap. Otherwise, the memory of the generated array is statically allocated on the stack. See Control Memory Allocation for Variable-Size Arrays.
If you choose C++ as your target language for code generation, by default, the dynamically allocated array is implemented as a class template called coder::array
in the generated code. To use dynamically allocated arrays in your custom C++ code that you integrate with the generated C++ functions, learn to use the coder::array
template.
Using the coder::array
Class Template
When you generate C++ code for your MATLAB functions, the code generator produces a header filecoder_array.h
in the build folder. This header file contains the definition of the class template array
in the namespacecoder
. The coder::array
template implements the dynamically allocated arrays in the generated code. The declaration for this template is:
template <typename T, int32_T N> class array
The array contains elements of type T
and has N
dimensions. For example, to declare a two-dimensional dynamic arraymyArray
that contains elements of type int32_T
in your custom C++ code, use:
coder::array<int32_T, 2> myArray
To use dynamically allocated arrays in your custom C++ code that you want to integrate with the generated code (for example, a custom main function), include thecoder_array.h
header file in your custom .cpp
files. This table shows the API you use to create and interact with dynamic arrays in your custom C++ code.
Action | Instructions |
---|---|
Declare a dynamic array myArray that contains elements of type int32_T. Set the number of dimensions of myArray to2. | Use the coder::array template. Specify element type and number of dimensions.coder::array<int32_T, 2> myArray |
Allocate memory for myArray. Set the size of the first dimension to 1 and the second dimension to 100. | Use the set_size method.myArray.set_size(1, 100)If the dimension of myArray changes later on during execution, the generated code reallocates memory based on the new size. |
Access the size vector ofmyArray. | Access the size array, which is a data member of myArray. For example, to access the size of the second dimension of myArray, use:myArray.size(1) |
Index into the dynamic arraymyArray. | Use the standard C++ syntax for array indexing. For example, to set the i-th element ofmyArray equal to i, use:myArray[i] = iTo index into multidimensional arrays, use the at method.myArray[i][j] = i*j; // You can also use the 'at' function myArray.at(i,j) = i * j; |
Create coder::array variables fromstd::string andstd::vector arrays. | Use the copy constructor to createcoder::array arrays fromstd::string andstd::vector arrays. For example, to create acoder::array copy of thestd::vector array vec, use:std::vector<int32_T> vec; // Create coder::array copy coder::array<int32, 2> copyArray(vec);UsecopyArray to interface the generated code with your project. |
Examples
The following examples show how to generate C++ code that accepts and returns variable-size numeric and character arrays. To use dynamically allocated arrays in your custom C++ code include the coder_array.h
header file in your custom.cpp
files. The coder::array
class template has methods that allow you to allocate and free array memory.
You can also interface the generated code with arrays ofstd::vector
or std::string
as dynamic size arrays. These arrays can also be used as inputs to the generated functions. See Generate C++ Code That Accepts and Returns a Variable-Size Vector of Characters.
Generate C++ Code That Accepts and Returns a Variable-Size Numeric Array
This examples shows how to customize the generated example main function to use the coder::array
class template in your project. See the table above for information about its associated methods.
Your goal is to generate a C++ executable for xTest1
that can accept and return an array of int32_T
elements. You want the first dimension of the array to be singleton and the second dimension to be unbounded.
- Define a MATLAB function
xTest1
that accepts an arrayX
, adds the scalarA
to each of its elements, and returns the resulting arrayY
.
function Y = xTest1(X, A)
Y = X;
for i = 1:numel(X)
Y(i) = X(i) + A;
end - Generate initial source code for
xTest1
. Use the following commands:
cfg = coder.config('lib'); cfg.TargetLang = 'C++';
codegen -config cfg -args { coder.typeof(int32(0), [1 inf]), int32(0)} xTest1.m -report
The function prototype forxTest1
in the generated code is shown here:
void xTest1(const coder::array<int, 2U> &X, int A, coder::array<int, 2U> &Y)
Interface the generated code by providing input and output arrays that are compatible with the function prototype shown above. - Define a C++ main function in the file
xTest1_main.cpp
in your current working folder.
This main function includes the header filecoder_array.h
that contains thecoder::array
class template definition. The main function uses the API described in the table in the previous section to perform these actions:- Declare
myArray
andmyResult
as two-dimensional dynamic arrays ofint32_T
elements. - Dynamically set the sizes of the two dimensions of
myArray
to1
and100
by using theset_size
method. - Access the size vector of
myResult
by usingmyResult.size
.
- Declare
#include
#include<coder_array.h>
#include"xTest1.h"
int main(int argc, char *argv[])
{
static_cast(argc);
static_cast(argv);
// Instantiate the input variable by using coder::array template
coder::array<int32_T, 2> myArray;
// Allocate initial memory for the array
myArray.set_size(1, 100);
// Access array with standard C++ indexing
for (int i = 0; i < myArray.size(1); i++) {
myArray[i] = i;
}
// Instantiate the result variable by using coder::array template
coder::array<int32_T, 2> myResult;
// Pass the input and result arrays to the generated function
xTest1(myArray, 1000, myResult);
for (int i = 0; i < myResult.size(1); i++) {
if (i > 0) std::cout << " ";
std::cout << myResult[i];
if (((i+1) % 10) == 0) std::cout << std::endl;
}
std::cout << std::endl;
return 0;
}
4. Generate code by running this script:
cfg = coder.config('exe'); cfg.TargetLang = 'C++';
cfg.CustomSource = 'xTest1_main.cpp';
cfg.CustomInclude = '.'; %current working directory
codegen -config cfg -args { coder.typeof(int32(0), [1 inf]), int32(0)} xTest1_main.cpp xTest1.m -report
The code generator produces an executable file xTest1.exe
in your current working folder.
Generate C++ Code That Accepts and Returns a Variable-Size Vector of Characters
This example shows how to customize the generated example main file to interface string arrays with the generated code by using the coder::array
class methods.
The main function in this example uses std::vector
to declare the vector vec
of char_T
elements that you pass to the generated C++ function xStringTest
.
- Define a MATLAB function
xStringTest
that accepts a character vectorstr
, insertsstr
between the character vectors'hello '
and' world!'
, and returns the result. Your goal is to generate a C++ executable fromxStringTest
.
function y = xStringTest(str)
assert(isa(str, 'char'));
assert(size(str,1) == 1);
assert(size(str,2) >= 0);
y = ['hello ' str ' world!']; - Generate source code for
xStringTest
. Use the following commands:
cfg = coder.config('lib'); cfg.TargetLang = 'C++';
codegen -config cfg -args {coder.typeof(char('X'), [1 inf])} xStringTest.m -report
In the report, check the function prototype forxStringTest
in the generated code.
void xStringTest(const coder::array<char, 2U> &str, coder::array<char, 2U> &y)
Interface the generated code by providing input and output arrays that are compatible with the function prototype shown above. - Define a C++ main function in the file
xStringTest_main.cpp
in your current working folder.
This main function defines the input array as anstd::vector
array ofchar_T
. Thefor
-loop initializesvec
with character values from'A'
to'J'
. This array is the input to the generated function forxStringTest
. The output of the function is returned in thecoder::array
variableresult
.
#include
#include<coder_array.h>
#include<xStringTest.h>
int main(int, char *[])
{
// Instantiate the result variable by using coder::array template
coder::array<char_T, 2> result;
// Instantiate the input variable by using std::vector
std::string vec;
// Resize the input to include required values
vec.resize(10);
vec = "ABCDEFGHIJ";
// Pass the input and result arrays to the generated function interface
xStringTest(vec, result);
//Cast coder::array 'result' variable to std::string to display it
std::cout << "Result is ";
std::cout << static_cast<std::string>(result) << std::endl;
return 0;
}
4. Generate code by running this script.
cfg = coder.config('exe'); cfg.TargetLang = 'C++';
cfg.CustomSource = 'xStringTest_main.cpp';
cfg.CustomInclude = '.'; %current working directory
codegen -config cfg -args {coder.typeof(char('X'), [1 inf])} xStringTest_main.cpp xStringTest.m -report
The code generator produces an executable file xStringTest.exe
in your current working folder.
Generate C++ Code That Accepts and Returns an N-Dimensional Array
Your goal is to generate a C++ executable for xTest2
that can accept and return an N-dimensional array of int32_T
elements.
- Define a function
xTest2
that accepts an 3-dimensional arrayX
, subtracts the scalarA
from each of its elements, and returns the resulting array inY
.
function Y = xTest2(X,A)
Y = X;
for i = 1:size(X,1)
for j = 1:size(X,2)
for k = 1:size(X,3)
Y(i,j,k) = X(i,j,k) - A;
end
end
end
end - Generate initial source code for
xTest2
. Use the following commands:
cfg = coder.config('lib'); cfg.TargetLang = 'C++';
codegen -config cfg -args {coder.typeof(0,[inf inf inf]),0} xTest2.m -report
The function prototype forxTest2
in the generated code is shown here:
xTest2(const coder::array<double, 3U> &X, double A,...
coder::array<double, 3U> &Y);
Interface the generated code by providing input and output arrays that are compatible with the function prototype shown above. - Define a C++ main function in the file
xTest2_main.cpp
in your current working folder.
This main function includes the header filecoder_array.h
that contains thecoder::array
class template definition. The main function uses the API described in the table in the previous section to perform these actions:- Declare two three-dimensional arrays as the input and output to the generated function,
myArray
andmyResult
. - Set the dimension sizes of
myArray
to4
by using theset_size
method. - Access the size vector of
myResult
by usingmyResult.size
.
- Declare two three-dimensional arrays as the input and output to the generated function,
#include
#include<coder_array.h>
#include"xTest2.h"
int main()
{
// Instantiate the input variable by using coder::array template
coder::array<double, 3U> myArray;
// Allocate initial memory for the array
myArray.set_size(4, 4, 4);
// Access array with standard C++ indexing
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++){
for (int k = 0; k < 4; k++) {
myArray.at(i,j,k) = i * j * k;
}
}
}
// Instantiate the result variable by using coder::array template
coder::array<double, 3U> myResult;
// Pass the input and result arrays to the generated function
xTest2(myArray, 1, myResult);
for (int i = 0; i < myResult.size(1); i++) {
if (i > 0) std::cout << " ";
for (int j = 0; j < 4; j++){
for (int k = 0; k < 4; k++){
std::cout << myResult.at(i,j,k) << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}
std::cout << std::endl;
return 0;
}
}
4. Generate the executable by running the following command:
cfg = coder.config('exe'); cfg.TargetLang = 'C++';
cfg.CustomSource = 'xTest2_main.cpp';
cfg.CustomInclude = '.'; %current working directory
codegen -config cfg -args { coder.typeof(0, [inf inf inf]), 0} xTest2_main.cpp xTest2.m -report
The code generator produces an executable filexTest2.exe
in your current working folder.
Change Interface Generation
By default, the generated C++ code uses the coder::array
template to implement dynamically allocated arrays. Instead, you can choose to generate C++ code that uses the C style emxArray
data structure to implement dynamically allocated arrays. To generate C style emxArray
data structures, do one of the following:
- In a code configuration object (coder.MexCodeConfig, coder.CodeConfig, or coder.EmbeddedCodeConfig), set the
DynamicMemoryAllocationInterface
parameter to'C'
. - In the MATLAB Coderâ„¢ app, on the Memory tab, setDynamic memory allocation interface to
Use C style EmxArray
.
To learn more about statically allocated arrays or dynamically allocated arrays implemented by using the C style emxArray
data structure, see Use C Arrays in the Generated Function Interfaces.