Use Dynamically Allocated C++ Arrays in the 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.

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.

Examples of C++ Function Interfaces with Dynamically Allocated Arrays

This table lists two typical cases for dynamic array representation in the generated C++ code. The next section explains the definition of the coder::array template that implements the dynamic array in the generated code.

Algorithm Description and Array Size

MATLAB Function

Generated C++ Function Interface

Push ones onto a variable-size row vector bounded at 30,000 elements.

Variable-size, not bounded within threshold.

function B = create_vec2 %#codegen
B = zeros(1,0);
coder.varsize('B',[1 30000],[0 1]);
for i = 1:500
    if round(rand)
        B = [1 B];
    end
end
void create_vec2(coder::array<double, 2U> &B)

Create an array with size determined by an unbounded integer input.

Unknown at compile time.

function y = create_vec3(n) %#codegen
y = int8(ones(1,n));
void create_vec3(double n, coder::array<signed char, 2U> &y)

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
The array contains elements of type T and has N dimensions. For example, to declare a 2-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

How To

Declare a dynamic array myArray that contains elements of type int32_T. Set the number of dimensions of myArray to 2.

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 in execution, the generated code reallocates memory based on the new size.

Access the size vector of myArray.

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 array myArray.

Use the usual C++ syntax for array indexing. For example, to set the i-th element of myArray equal to i, use:

myArray[i] = i

Examples

Generate C++ Code That Accepts and Returns a Variable-Size Numeric Array

Define a MATLAB function xTest1 that accepts an array X, 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

You 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 C++ main function in the file xTest1_main.cpp in your current working folder.

#include<iostream>
#include<coder_array.h>
#include<xTest1.h>

int main(int argc, char *argv[])
{
    static_cast<void>(argc);
    static_cast<void>(argv);

    coder::array<int32_T, 2> myArray;
    myArray.set_size(1, 100);
    for (int i = 0; i < myArray.size(1); i++) {
        myArray[i] = i;
    }

    coder::array<int32_T, 2> myResult;
    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;
}

This main function includes the header file coder_array.h that contains the coder::array class template definition. The main function uses the API described in the table in the previous section to perform these actions:

  • Declare myArray and myResult as 2-dimensional dynamic arrays of int32_T elements.

  • Dynamically set the sizes of the two dimensions of the myArray to 1 and 100 by using the set_size method.

  • Access the size vector of myResult by using myResult.size.

Generate code by running this script. Replace 'C:\work' by the path to your current working folder.

cfg = coder.config('exe'); cfg.TargetLang = 'C++';
cfg.CustomSource = 'xTest1_main.cpp';
cfg.CustomInclude = 'C:\work';
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

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!'];

Define a C++ main function in the file xStringTest_main.cpp in your current working folder. This main function uses std::vector to declare the vector vec of char_T elements that you pass to the generated C++ function xStringTest.

#include<iostream>
#include<coder_array.h>
#include<xTest1.h>

int main(int, char *[])
{
    coder::array<char_T, 2> result;
    
    std::vector<char_T> vec;
    vec.resize(10);
    for (size_t i = 0; i < 10; i++) {
        vec[i] = static_cast<char_T>('A' + i);
    }
    
    xStringTest(vec, result);
    
    std::cout << "Result is " << static_cast<std::string>(result) << std::endl;
    
    return 0;
}

Generate code by running this script. Replace 'C:\work' by your current working folder.

cfg = coder.config('exe'); cfg.TargetLang = 'C++';
cfg.CustomSource = 'xStringTest_main.cpp';
cfg.CustomInclude = 'C:\work';
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.

See Also

|

Related Topics