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.

  1. Define a MATLAB function xTest1 that accepts an arrayX, adds the scalar A to each of its elements, and returns the resulting array Y.
    function Y = xTest1(X, A)
    Y = X;
    for i = 1:numel(X)
    Y(i) = X(i) + A;
    end
  2. 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.
  3. 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 of int32_T elements.
    • Dynamically set the sizes of the two dimensions ofmyArray to 1 and100 by using theset_size method.
    • Access the size vector of myResult by usingmyResult.size.

#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.

  1. Define a MATLAB function xStringTest that accepts a character vector str, inserts str between the character vectors 'hello ' and ' world!', and returns the result. Your goal is to generate a C++ executable from xStringTest.
    function y = xStringTest(str)
    assert(isa(str, 'char'));
    assert(size(str,1) == 1);
    assert(size(str,2) >= 0);
    y = ['hello ' str ' world!'];
  2. 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.
  3. Define a C++ main function in the filexStringTest_main.cpp in your current working folder.
    This main function defines the input array as anstd::vector array of char_T. Thefor-loop initializes vec 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 the coder::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.

  1. Define a function xTest2 that accepts an 3-dimensional array X, subtracts the scalar A 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
  2. 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.
  3. 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.

#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:

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.

See Also

coder.typeof | coder.varsize