Use Dynamically Allocated C++ Arrays in Generated Function Interfaces
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 file
coder_array.h
in the build folder. This header file contains the
definition of the class template array
in the namespace
coder
. 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
T
and has N
dimensions. For example, to declare a two-dimensional dynamic array
myArray
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 the
coder_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 | Use the coder::array<int32_T, 2> myArray |
Allocate memory for | Use the myArray.set_size(1, 100) If
the dimension of |
Access the size vector of
| Access the myArray.size(1) |
Index into the dynamic array
| Use the standard C++ syntax for array indexing. For example, to
set the myArray[i] = i To
index into multidimensional arrays, use the myArray[i][j] = i*j; // You can also use the 'at' function myArray.at(i,j) = i * j; |
Create | Use the copy constructor to create
std::vector<int32_T> vec; // Create coder::array copy coder::array<int32, 2> copyArray(vec); Use
|
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 of
std::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 for
xTest1
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 file
coder_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
.
#include<iostream> #include<coder_array.h> #include"xTest1.h" int main(int argc, char *argv[]) { static_cast<void>(argc); static_cast<void>(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; }
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 for
xStringTest
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 an
std::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<iostream> #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; }
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 for
xTest2
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 file
coder_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
.
#include<iostream> #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; } }
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 file
xTest2.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
, orcoder.EmbeddedCodeConfig
), set theDynamicMemoryAllocationInterface
parameter to'C'
.In the MATLAB Coder™ app, on the Memory tab, set Dynamic 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.