Generate C++ Code with Class Interface
When you generate C/C++ code, the software analyzes your MATLAB® code and generates entry-point C/C++ functions that correspond to your entry-point MATLAB functions by default.
Alternatively, if you generate C++ code, you can choose to generate entry-point functions as methods in a C++ class. By using this option:
You obtain more object-oriented code.
The code generator produces a class constructor and destructor that automatically perform memory initialization and termination.
You allocate memory for each class instance separately. The methods for each class instance are thread-safe and reentrant.
Multiple entry-point functions become methods in a single C++ class.
To generate C++ code with a class interface, use one of these approaches:
In a configuration object, set the
Languageproperty to"C++"and set theCppInterfaceStyleproperty to"Methods". Optionally, specify a name for the C++ interface class by using theCppInterfaceClassNameproperty.In the Code Generation Settings dialog box, set the Language parameter to
C++and the Interface style parameter toEach entry-point function is generated as a method in a C++ class. Optionally, use the C++ interface class name parameter to specify a name for the C++ interface class.
These examples show the command-line workflow.
Generate C++ Code with a Class Interface
This example shows how the generated C++ code differs when it uses a class interface.
MATLAB Algorithm
Consider a simple MATLAB function that performs operations on a matrix and outputs the result.
function out = foog %#codegen I = eye(447); out = ones(447)*I + 7;
Generate C++ Code with and Without Class Interface
To generate C++ code with a class interface, use the CppInterfaceStyle and CppInterfaceClassName parameters. Store the output in the withClass folder.
cfg = coder.config('lib'); cfg.GenCodeOnly = true; cfg.TargetLang = 'C++'; cfg.CppInterfaceStyle = 'Methods'; cfg.CppInterfaceClassName = 'myClass'; codegen foog -config cfg -report -d withClass
Code generation successful: To view the report, open('withClass/html/report.mldatx')
Next, create a new configuration object and generate C++ code that does not use a class interface.
cfg = coder.config('lib'); cfg.GenCodeOnly = true; cfg.TargetLang = "C++"; codegen foog -config cfg -report -d withoutClass
Code generation successful: To view the report, open('withoutClass/html/report.mldatx')
Inspect the generated example main function. Compare the versions with and without the class interface. With the class interface, the main function calls the entry-point function as a class method.
type withClass/examples/main.cpp
Class Definition and Implementation in the Generated Code
When the code generator produces code for the C++ interface class, it ensures that the function methods are reentrant. If the function methods use variables that can exceed the local stack memory limit, set by the configuration parameter StackUsageMax, then the code generator produces private data structures for the variables (identifiable by the suffix StackData), rather than declaring the variables as static. Static variables persist between function calls and are not reentrant. For information on generating reentrant C code, see Generating and Calling Reentrant Code.
To explore the generated class implementations, modify the function foog such that it contains a variable that exceeds the maximum stack usage specified by the configuration parameter StackUsageMax.
function out = foogBig %#codegen I = eye(448); out = ones(448)*I + 7;
The default value for StackUsageMax in bytes is:
cfg.StackUsageMax
ans = int32 200000
Because fooBig uses a variable of 448^2 (200704) elements, and the code generator produces an 8-bit integer array to represent the variable, the default stack usage limit is exceeded by 704 bytes. Generate code for foogBig.
cfg = coder.config('lib','ecoder',false); cfg.GenCodeOnly = true; cfg.TargetLang = 'C++'; cfg.CppInterfaceStyle = 'Methods'; cfg.CppInterfaceClassName = 'myBigClass'; codegen foogBig -config cfg -report -d withBigClass
Code generation successful: To view the report, open('withBigClass/html/report.mldatx')
Inspect the Generated Interface Class Definitions
Inspect the class definitions for the foogBig project and for foog. The foogBig class stores variables that can exceed the maximum stack usage in a private class property, whereas the foog class only creates local variables on the stack.
When you work with a class definition that contains a StackData structure, indicating that the class requires data that exceeds the local stack usage limit, then allocate heap memory for the class instance by using new. See the generated example main file for your generated code for an example.
Globals and Persistents in a Generated C++ Class
When you generate C++ code with a class interface, then you access globals and persistents as members of the class. This example shows how to interact with globals and persistents in the class.
MATLAB Algorithm
Consider a MATLAB function that keeps count of the number of times you call it with a global and persistent variable.
function [po,go] = countCalls %#codegen % increment persistent & global variable persistent p global g if isempty(p) p = 0; end p = p+1; g = g+1; % set output variables po = double(p); go = double(g);
Generate C++ Code with a Class Interface
For code generation, initialize the global variable in the workspace.
global g;
g = 0;
Generate code in the class called countClass.
cfg = coder.config('lib'); cfg.GenCodeOnly = true; cfg.TargetLang = 'C++'; cfg.CppInterfaceStyle = 'Methods'; cfg.CppInterfaceClassName = "countClass"; codegen countCalls -config cfg -report
Code generation successful: To view the report, open('codegen/lib/countCalls/html/report.mldatx')
Inspect the Class Definition
In the generated C++ code, an initialization function sets the global variable to the value that you specify in the workspace. You can also specify the initial global value with the codegen -globals syntax.
Inspect the code for the class definition in the header file countClass.h.
type codegen/lib/countCalls/countClass.h
The global variable is a public member of the class. Access this variable from your main function as needed. The persistent variable is stored in a private class data structure.
Put Multiple Entry-Point Functions in the Same Class
When you generate C++ code for multiple entry-point functions and use the class interface setting, then each function becomes a public method of the same class. You can use this technique to create a simpler interface to your multiple entry-point function project.
MATLAB Entry-Point Functions
Break the function countCalls in the previous example into two, so that one function counts the calls with a persistent variable and the other counts the calls with a global variable. Inspect the two functions.
function po = countPersistent %#codegen % increment persistent variable persistent p if isempty(p) p = 0; end p = p+1; % set output variable po = double(p);
function go = countGlobal %#codegen % increment global variable global g g = g+1; % set output variable go = double(g);
Generate C++ Code
Use the codegen command and specify the initial global variable value as an input.
cfg = coder.config('lib'); cfg.GenCodeOnly = true; cfg.TargetLang = 'C++'; cfg.CppInterfaceStyle = 'Methods'; cfg.CppInterfaceClassName = 'countClassMulti'; codegen countGlobal countPersistent -config cfg -report -globals {'g',0}
Code generation successful: To view the report, open('codegen/lib/countGlobal/html/report.mldatx')
Inspect the Generated Code
To see the generated class definition, open countClassMulti.h. Each entry-point function is a public method of the class.
type codegen/lib/countGlobal/countClassMulti.h