Main Content

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
The array contains elements of type 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 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 during 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 standard C++ syntax for array indexing. For example, to set the i-th element of myArray equal to i, use:

myArray[i] = i

To 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 from std::string and std::vector arrays.

Use the copy constructor to create coder::array arrays from std::string and std::vector arrays. For example, to create a coder::array copy of the std::vector array vec, use:

std::vector<int32_T> vec;
// Create coder::array copy
coder::array<int32, 2> copyArray(vec);

Use copyArray 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 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.

  1. 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
  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 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 two-dimensional dynamic arrays of int32_T elements.

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

    • Access the size vector of myResult by using myResult.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;
    }
  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 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.

  3. 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 of char_T. The for-loop initializes vec with character values from 'A' to 'J'. This array is the input to the generated function for xStringTest. The output of the function is returned in the coder::array variable result.

    #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;
    }
    
  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 in Y.

    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 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 two three-dimensional arrays as the input and output to the generated function, myArray and myResult.

    • Set the dimension sizes of myArray to 4 by using the set_size method.

    • Access the size vector of myResult by using myResult.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;
    }
    }
  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 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:

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

|

Related Topics