Generate C++ Code with Class Interface
When you generate C code, the software analyzes your MATLAB® code and generates entry-point C functions corresponding to your entry-point MATLAB functions. When you generate C++ code, you can choose to generate entry-point functions as methods in a C++ class. 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.
You can generate code with a class interface from the command line or from the
MATLAB
Coder™ app. From the command line, use the CppInterfaceStyle
and CppInterfaceClassName
configuration parameters. From the app, on
the Generate Code step, select Language as
C++, select Interface style as
Methods, and then specify the C++ interface class
name.
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