Programmatically Configure C++ Interface
To streamline the integration of C++ code generated from Simulink® applications, components, and subsystems with external C or C++ code, configure a customized C++ class interface. When you generate C++ code from a model, the model appears as a class, the data elements appear as class members, and the model functions appear as class methods in the generated code. Configuring a C++ class interface enables you to customize the following aspects of the generated C++ code:
Class information — Class name and namespace
Class member information — Class member access and visibility
Class method information — Class method names and arguments
A customized C++ class interface enables the generated classes to meet specific code standards or interface requirements so that the generated code can compile and integrate into larger architectures with minimal post-generation customization.
Programmatic Workflow Overview
The programmatic workflow uses a programmatic interface that you can call into by using the MATLAB® command line or a MATLAB script to configure a customized C++ class interface. Additionally, you can use the functions to facilitate scripting, automated testing, and developing or utilizing downstream features. The programmatic interface is composed of the following functions:
To create or retrieve the Code Mappings object to configure a customized C++ Class interface, you can use the functions
coder.mapping.utils.create
andcoder.mapping.api.get
.To configure the class name and namespace, you can use the functions
getClassName
,setClassName
,getClassNamespace
, andsetClassNamespace
.To configure how data elements appear as class members, you can use the functions
getData
andsetData
.To configure how model functions appear as class methods, you can use the functions
find
,getFunction
, andsetFunction
.
To programmatically configure a customized C++ interface, follow the outlined workflow:
Open Environment
Open the environment for configuring a customized C++ class interface:
Open the model and the MATLAB command prompt.
This workflow uses the model
CppClassWorkflowKeyIgnition
, which is a supporting file in an existing example. Alternatively, you can create a MATLAB configuration script.openExample("CppClassWorkflowKeyIgnition")
Set model configuration parameters. These parameters configure model-wide code generation behavior. To configure parameters specific to generating a customized C++ class interface, you can use the
set_param
function to set these parameters:Configuration Parameter Description Code interface packaging Selects output language for generated code. For more information, see Code interface packaging. Multi-instance code error diagnostic Specifies the severity level for diagnostics displayed when a model violates requirements for generating multi-instance code. For more information, see Multi-instance code error diagnostic.
Remove error status field in real-time model data structure Specifies whether to omit the error status field from the generated real-time model data structure
rtModel
. For more information, see Remove error status field in real-time model data structure.Include model types in model class Specifies to include model type definitions within the class namespace of the model. For more information, see Include model types in model class.
Interface parameters that are related, but are less commonly used:
Configuration Parameter Description Terminate function required Specifies whether to generate the
method. For more information, see Terminate function required.model
_terminateCombine signal/state structures Specifies whether to combine global block signals and global state data into one data structure in the generated code. For more information, see Combine signal/state structures.
Generate destructor Specifies whether to generate a destructor for the C++ model class. For more information, see Generate destructor.
Use dynamic memory allocation for model block instantiation Specifies memory allocation for model hierarchies. For more information, see Use dynamic memory allocation for model block instantiation.
To configure a customized C++ class interface for a model, create a Code Mappings object. To create a new Code Mappings object for a model, use the function
coder.mapping.utils.create
. If a Code Mappings object already exists for the model, the function returns the existing object.% Create a new Code Mappings object for a model cm = coder.mapping.utils.create(model);
Configure Model as Class
Configure the class name and namespace. When you generate C++ code from a model, that model appears as a class in the generated code. To ease integration and comply with code and interface requirements, you can customize the generated class name. Optionally, you can scope the generated code and prevent symbol clashes within a project by specifying a namespace for the generated class. In modeled systems that use a model hierarchy, you can specify a different namespace for each model in the hierarchy.
The generated C++ class interface, declared in the model header file, incorporates the customized name and namespace:
// File: CppClassWorkflowKeyIgnition.h namespace CustomizedNamespace { class customized_ModelClass { // public data and function members public: // private data and function members private: }; }
Workflow
To programmatically configure the class name and namespace, get the Code Mappings object for your model and set the name and namespace:
Get the Code Mappings object for your model. To get the object, use the function
coder.mapping.api.get
.% Get the Code Mappings object for a model cm = coder.mapping.api.get(model);
Configure the class name. To set the class name, use the function
setClassName
.% Set the class name setClassName(cm, 'customized_ModelClass');
To verify the new class name before generating code, use the function
getClassName
.% Get the class name getClassName(cm);
Configure the class namespace. To set the namespace, use the function
setClassNamespace
.% Set the class namespace setClassNamespace(cm, 'customized_namespace');
To configure a nested namespace, use the scope resolution operator
::
to specify scope.% Set a nested namespace setClassNamespace(cm, 'customized_namespace1::customized_namespace2');
To verify the new namespace before generating code, use the function
getClassNamespace
.% Get the class namespace getClassNamespace(cm);
Configure Model Data Elements as Class Members
Configure the visibility and access of class members. When you generate C++ code from a model, Simulink data elements appear as class members in the generated code. To adjust the encapsulation of the class data to meet code standards, security, or performance requirements, you can customize the visibility and access of the generated class members. Simulink data elements can be grouped into the following categories of modeling elements:
Model Element Category | Description |
---|---|
Inports | Root-level data input ports of a model, such as Inport and In Bus Element blocks. For more information, see Inport. |
Outports | Root-level data output ports of a model, such as Outport and Out Bus Element blocks. For more information, see Outport. |
Model parameter arguments | Workspace variables that appear as instance (nonstatic) class data members. |
Model parameters | Workspace variables that are shared across instances of the model class and are generated as static class data members. |
Signals, states, and internal data | Data elements that are internal to a model, such as block output signals, discrete block states, data stores, and zero-crossing signals. |
For each model element category, you can configure the data visibility to control the access modifier (access specifier) of the generated class members. Each option and its impact on the generated C++ class interface, declared in the model header file, is outlined in this table.
Data Visibility Options | Description |
---|---|
public | If you configure data elements as
File: CppClassWorkflowKeyIgnition.h namespace CustomizedNamespace { class customized_ModelClass { public: // example inport ExtU rtU; // example outport ExtY rtY; // example block signals and states DW rtDW; // Other data, methods, and types (not shown) private: … }; } |
protected | If you configure data elements as File: CppClassWorkflowKeyIgnition.h // Class declaration for model example_model namespace CustomizedNamespace { class customized_ModelClass { public: protected: // example inport ExtU rtU; // example outport ExtY rtY; // example block signals and states DW rtDW; // Other data, methods, and types (not shown) private: … }; } |
private | If you configure elements as File: CppClassWorkflowKeyIgnition.h namespace CustomizedNamespace { class customized_ModelClass { public: private: // example inport ExtU rtU; // example outport ExtY rtY; // example block signals and states DW rtDW; // Other data, methods, and types (not shown) }; } |
Individual arguments (Model parameter arguments
only) | If you configure model parameter arguments with visibility set to
The File: CppClassWorkflowKeyIgnition.h namespace CustomizedNamespace { class customized_ModelClass { public: // model step function void step1(real_T rty_engineState, const real_T modelParameterArgument); // Other data, methods, and types (not shown) private: … }; } |
After you set the data visibility of a model element category, you can configure the member access method to determine how the get and set methods are generated for the data elements. This configuration controls how application code can view and modify the class member data. Each option and its impact on the generated C++ class interface, declared in the model header file, is outlined in this table.
Member Access Method Options | Description |
---|---|
Method | If you configure inports as File: CppClassWorkflowKeyIgnition.h namespace CustomizedNamespace { class customized_ModelClass { public: // example inport void setInport(real_T localArgInput); // example outport real_T getOutport() const; // example of model parameter arguments configured with // ‘DataAccess’ ‘Direct' real_T const &getInstP() const; // example of model parameter arguments configured with // ‘DataAccess’ ‘Pointer’ // real_T const *getInstP() const; // example Block parameters get and set methods const P &getBlockParameters() const; void setBlockParameters(const P *pP) const; // example Block states get and set methods const DW &getDWork() const; void setDWork(const DW *pDW); private: … }; } |
Inlined method | If you configure inports as File: CppClassWorkflowKeyIgnition.h namespace CustomizedNamespace { class customized_ModelClass { public: // example inport set method void setkeyState(real_T localArgInput) { rtU.keyState = localArgInput; } // example outport get method const real_T *getengineState() const { return rtY.engineState; } // example Block parameters get and set method const P &getBlockParameters() const { return rtP; } void setBlockParameters(const P *pP) const { rtP = *pP; } // example Block states get and set methods const DW &getDWork() const { return rtDW; } void setDWork(const DW *pDW) { rtDW = *pDW; } private: … }; } |
Structure-based method | If you configure the inports as File: CppClassWorkflowKeyIgnition.h namespace CustomizedNamespace { class customized_ModelClass { // public data and function members public: // External inputs (root inport signals with default storage) struct ExtU { real_T keyState; // '<Root>/keyState' }; // External outputs (root outports fed by signals with default storage) struct ExtY { real_T engineState[3]; // '<Root>/engineState' real_T cycleTime; // '<Root>/cycleTime' }; … // example inport void setExternalInputs(const ExtU *pExtU); // example outport const ExtY &getExternalOutputs() const; // Other model element categories may not be configured as ‘Structure-based method’ private: … }; } |
Inlined structure-based method | If you configure the inports as File: CppClassWorkflowKeyIgnition.h namespace CustomizedNamespace { class customized_ModelClass { public: // External inputs (root inport signals with default storage) struct ExtU { real_T keyState; // '<Root>/keyState' }; // External outputs (root outports fed by signals with default storage) struct ExtY { real_T engineState[3]; // '<Root>/engineState' real_T cycleTime; // '<Root>/cycleTime' }; … // example inport void setExternalInputs(const ExtU *pExtU); // example outport const ExtY &getExternalOutputs() const; // example inport void setExternalInputs(const ExtU *pExtU) { rtU = *pExtU; } // example outport const ExtY &getExternalOutputs() const { return rtY; } // Other model element categories may not be configured as ‘Inlined structure-based method’ private: … }; } |
None | If you configure the access of a model element category as
File: CppClassWorkflowKeyIgnition.h namespace CustomizedNamespace { class customized_ModelClass { public: // External inputs (root inport signals with default storage) struct ExtU { real_T keyState; // '<Root>/keyState' }; // External outputs (root outports fed by signals with default storage) struct ExtY { real_T engineState[3]; // '<Root>/engineState' real_T cycleTime; // '<Root>/cycleTime' }; … // External inputs ExtU rtU; // External outputs ExtY rtY; private: … }; } |
For each model element category, valid data visibility and member access method combinations are outlined in this table.
Model Element Category | Data Visibility | Member Access Method |
---|---|---|
Inports | private | Method Inlined method Structure-based method Inlined structure-based method |
protected | Method Inlined method Structure-based method Inlined structure-based method | |
public | None Method Inlined method Structure-based method Inlined structure-based method | |
Outports | private | Method Inlined method Structure-based method Inlined structure-based method |
protected | Method Inlined method Structure-based method Inlined structure-based method | |
public | None Method Inlined method Structure-based method Inlined structure-based method | |
Model parameter arguments | Individual arguments | None |
private | Method Inlined method | |
Model parameters | private | None Method Inlined method |
protected | None Method Inlined method | |
public | None Method Inlined method | |
Signals, states, and internal data | private | None Method Inlined method |
protected | None Method Inlined method | |
public | None Method Inlined method |
For model parameter arguments, you can configure block parameters to be
instance-specific or shared when the visibility is private
. See
Configure Parameters for C++ Interface Code Generation for more information.
To configure Individual arguments
visibility for model
parameter arguments, the model must be a referenced model. Only referenced models can
generate methods that use individual arguments.
For inports, outports, and model parameter arguments, you can additionally specify
whether the data for the model element category is stored by value
('Direct'
) or pointer ('Pointer'
) in the generated
code.
When configuring data access for Inports or
Outports as pointer members, the model must have model
configuration parameters set to either generate an example ERT main program
(ert_main.cpp
) or generate code only. Additionally, the data access
method for the inports or outports must be structure-based. To configure the data access
method for model parameter arguments, data visibility cannot be set to
Individual arguments
.
Workflow
To programmatically configure class member visibility and access, get the Code Mappings object for the model and set the access and visibility properties:
Get the Code Mappings object for the model. To get the object, use the function
coder.mapping.api.get
.% Get the Code Mappings object cm = coder.mapping.api.get(model);
Configure the visibility. To set the data visibility of a category of Simulink data elements in the generated code, use the function
setData
. When you use thesetData
function, specify the Code Mappings object, model element category, data visibility property, and data visibility option. Valid data visibility options vary depending on the model element category.% Set the data visibility of Simulink model data elements by category % setData(Code Mappings object, model element category, 'DataVisibility', data visibility option) setData(cm, 'Outports', 'DataVisibility', 'private');
To verify the data visibility setting before generating code, use the function
getData
:% Get the data visibility of Simulink model data elements by category % getData(Code mappings object, model element category, 'DataVisibility') getData(cm, 'Outports', 'DataVisibility');
Configure the member access. To set the member access method of a category of Simulink data elements in the generated code, use the function
setData
. When you use thesetData
function, specify the Code Mappings object, model element category, member access method property, and member access method option. Valid member access method options vary depending on the model element category and selected data visibility option.% Set the access of Simulink model data elements by category % setData(Code Mappings object, model element category,... % 'MemberAccessMethod', member access method option) setData(cm, 'Inports', 'MemberAccessMethod', 'Structure-based method');
To verify the member access method setting before generating code, use the function
getData
:% Get the member access method of Simulink model data elements by category % getData(Code Mappings object, model element category, 'MemberAccessMethod') getData(cm, 'Inports', 'MemberAccessMethod');
Configure the data access for model element inports, outports, or model parameter arguments.
'Inports'
or'Outports'
– Can be configured as pointer or direct access for inports or outports whose member access method is set to'Structure-based method'
or'Inlined structure-based method'
. The default configuration is direct access.'ModelParameterArguments'
– Can be configured as pointer or direct access for model parameter arguments whose data visibility is set to'private'
(not'Individual Arguments'
).
To configure data access, use the function
setData
.For example:
% For inports, verify the member access method is structure-based getData(cm, 'Inports', 'MemberAccessMethod'); % Set the data access method for inports % setData(Code Mappings object, model element category, 'DataAccess', value) setData(cm, 'Inports', 'DataAccess', 'Pointer'); % For model parameter arguments, verify the visibility is private getData(cm, 'ModelParameterArguments', 'DataVisibility'); % Set the data access method for model parameter arguments setData(cm, 'ModelParameterArguments', 'DataAccess', 'Direct'); % Get the data access method of Simulink model data elements by category % getData(Code Mappings object, model element category, 'DataAccess') getData(cm, 'Inports', 'DataAccess');
Configure Model Functions as Class Methods
Configure the class method names and arguments. When you generate C++ code from a model, model functions appear as class methods in the generated code. To integrate with external code or interface requirements, you can customize the name of the generated class methods. Additionally, for base-rate periodic functions and Simulink Functions, you can configure the name, order, and identifier of the generated arguments.
The generated class methods are referred to as entry-point methods and are locations in code where a transfer of program control (execution) occurs. Entry-point methods vary depending on the type of Simulink model and can be grouped into the following types:
Model Type | Type of Model Function | Description | Name of Model Function | Expected Method Name |
---|---|---|---|---|
Export-Function Models | Exported function | The exported function for a subsystem. | ExportedFunction: ,
where is the name of
the function-call Inport block in the model |
or (if
specified) |
Simulink Function | The exported function for a Simulink Function block. | Simulink
Function: where
is the name of
the Simulink Function block in the model | for a global
Simulink Function block or
for a scoped Simulink Function block | |
Export-Function or Rate-based Models | Initialize function | Initialization code for a model. At the start of the application
code, call the function once. Do not use this function to
reset the real-time model data structure
( | Initialize |
|
Partition function | For a model partition, output and update code. Model configuration parameter Single output/update function is selected (the default). | Partition: , where
is a partition
that was created explicitly from a block in the model and shown in the Simulink®
Schedule Editor (for example, P1) | ,
where uniquely identifies the
function generated for one of the model sample periods | |
Periodic multitasking function | For blocks in a rate-based model configured for multitasking, output and update code. The code generator produces a function for each sample period. Model configuration parameter Single output/update function is selected (the default). | Periodic: where
is an annotation
that corresponds to the sample time period for a periodic or continuous rate of
a multitasking model (for example, D1) | ,
where uniquely identifies the
function generated for one of the model sample periods | |
Periodic single-tasking function | For blocks in a rate-based model configured for single-tasking, output and update code. Model configuration parameter Single output/update function is selected (the default). | Periodic |
| |
Reset function | If the model includes a Reset Function block, reset code generated. To reset conditions or state, call the function from the application code. | Reset: where
is the name of
the reset function in the model |
| |
Terminate function | Code for turning off a system. For ERT-based models, you can suppress generation of this function by clearing the model configuration parameter Terminate function required (set by default). | Terminate |
|
The generated C++ class interface, declared in the model header file, incorporates the function name and argument customizations in the generated entry-point methods:
File: CppClassWorkflowKeyIgnition.h namespace CustomizedNamespace { class customized_ModelClass { public: // model initialize function- customized name void customized_initialize(); // model step function- customized name & arguments void customized_step(customArg1, const* customArg2); // model terminate function- customized name void customized_terminate(); // Constructor customized_ModelClass(); // Destructor ~customized_ModelClass(); private: … }; }
Workflow
To programmatically configure class method names and arguments, get the Code Mappings object for the model and set the function properties:
Get the Code Mappings object for the model. To get the object, use the function
coder.mapping.api.get
.% Get the Code Mappings object cm = coder.mapping.api.get(model);
To view the available entry-point methods for the model, use the function
find
. When you use thefind
function, specify the Code Mappings object and the function category you would like to view for the model. Valid function category options are the following:Functions
PeriodicFunctions
PartitionFunctions
ExportedFunctions
ResetFunctions
SimulinkFunctions
% View entry-point methods for a model by category % This example shows how to view the entry-point functions for a model % find(Code Mappings object, function category') find(cm, 'Functions');
Configure method names. To configure the method name of an entry-point method, use the function
setFunction
. When you use thesetFunction
function, specify the Code Mappings object, model function name, the method name property, and the custom name. Valid model function names are specified in the following way:Initialize
— Initialize function.Terminate
— Terminate function.Periodic:slIdentifier
— Periodic function (implicit task), whereslIdentifier
is the annotation (for example, D1) corresponding to the sample time period.Periodic
is sufficient for a single-tasking periodic function.Partition:slIdentifier
— Partition function (explicit task), whereslIdentifier
is the partition name in Schedule Editor.Reset:slIdentifier
— Reset function whereslIdentifier
is name of the reset function in model.ExportedFunction:slIdentifier
— Exported function whereslIdentifier
is the name of function-call inport block.ExportedFunction:slIdentifier
— Simulink function whereslIdentifier
is the name of Simulink function in model.
% Set the name of individual entry-point methods % This example shows how to customize the name of a periodic function % setFunction(Code Mappings object, model function, 'MethodName', custom name) setFunction(cm, 'Periodic', 'MethodName', 'custom_Periodic');
To verify the method name before generating code, use the function
getFunction
:% Get method name % getFunction(Code mappings object, model function, 'MethodName') getData(cm, 'Periodic', 'MethodName');
Configure method arguments. For base-rate periodic functions and Simulink Functions, you can use the function
setFunction
to configure the generated method arguments. When you use thesetFunction
function, specify the Code Mappings object, model function name, the arguments property, and the method prototype. Valid model function names are specified in the following way:Initialize
— Initialize function.Terminate
— Terminate function.Periodic:slIdentifier
— Periodic function (implicit task), whereslIdentifier
is the annotation (for example, D1) corresponding to the sample time period.Periodic
is sufficient for a single-tasking periodic function.Partition:slIdentifier
— Partition function (explicit task), whereslIdentifier
is the partition name in Schedule Editor.Reset:slIdentifier
— Reset function whereslIdentifier
is name of the reset function in model.ExportedFunction:slIdentifier
— Exported function whereslIdentifier
is the name of function-call inport block.ExportedFunction:slIdentifier
— Simulink function whereslIdentifier
is the name of Simulink function in model.
Valid identifier options for parameters are the following:
Identifier Option Preview Value (Inports only) myPeriodic(argInport) Const Reference (Inports only) myPeriodic(const & argInport) Pointer to Const myPeriodic(const * argInport) Pointer myPeriodic(* argInport) Const Pointer to const myPeriodic(const * const argInport) In the below example, the periodic function,
foo
, is configured to generate a method wherey
is the return argument and its parameteru1
is passed as a scalar andu2
is passed as a constant pointer:% Configure method arguments % setFunction(Code Mappings object, function, 'Arguments', function prototype) setFunction(cm, 'Periodic:foo', 'Arguments', 'y=(u1, const *u2)');
To verify the method arguments before generating code, use the function
getFunction
:% Get method name % getFunction(Code Mappings object, model function, 'Arguments') getData(cm, 'Periodic:foo', 'Arguments');
Generate C++ Class Interface
Generate the customized C++ class interface by generating code from the model. To verify your customized C++ class interface configurations, build the model and view the generated class, class member, and class method representations.
Generate code. To generate a C++ class interface, build the model with the command
slbuild
.slbuild example_model
View code. To view the generated code, open the model in the Embedded Coder® app.
To open the Code view, on the C++ Code tab, click View Code. The generated code appears beside the model in the model workspace.open example_model
Iterate. If the generated interface does not meet code requirements, make configuration adjustments until requirements are satisfied.
If the generated code representation does not meet your requirements, reconfigure the interface and generate code again until code generations requirements are satisfied. For guidance on understanding the generated code, see Analyze Generated Data Code Interface Report.
Considerations and Limitations
Instance-Specific Parameter Support — You can use model parameter arguments to configure workspace variables that have been specified as arguments. You can configure these arguments as private members of your class or as individual arguments defined outside the class. To configure within the class, you can set the data visibility setting to private and configure the generation of the get and set methods. Optionally, you can configure the class member values as defined within the class (
setData(cm,'ModelParameterArguments','DataAccess','Direct')
) or passed-by-reference through the class constructor (setData(cm,'ModelParameterArguments','DataAccess','Pointer')
). The data access setting is supported for top model builds. For reference model builds, the code is generated as references in the model class. To configure instance-specific parameters outside the class, set the data visibility toIndividual arguments
.Instance-specific parameter limitations include:
MATLAB variables marked as model arguments are not able to be configured as private class members.
Model parameter arguments are not supported by right-click builds.
Interface Code Generation Behavior — The I/O arguments style of step method specification supports single-rate models and multirate single-tasking models. Multirate multitasking models are not supported. Additionally, the C++ encapsulation interface is not the default, the value is ignored for the Pass fixed-size scalar root inputs by value for code generation parameter.
Stateflow® considerations — If you have a Stateflow license, for a Stateflow chart that resides in a root model configured to use the
I/O arguments step method
function specification, and that uses a model root inport value or calls a subsystem that uses a model root inport value, do one of the following to generate code:In the Stateflow chart, clear the Execute (enter) Chart At Initialization check box.
Insert a Simulink Signal Conversion block immediately after the root inport. In the Signal Conversion block parameters dialog box, select Exclude this block from 'Block reduction' optimization.
Simscape™ Considerations — If a model root inport value connects to a Simscape block, insert a Simulink Signal Conversion block between the root inport and the Simscape conversion block. In the Signal Conversion block parameters dialog box, select Exclude this block from 'Block reduction' optimization.
Reference Model Considerations — When building a referenced model that is configured to generate a C++ class interface:
Do not use a C++ class interface in cases when a referenced model cannot have a combined output/update function. Cases include a model that has a continuous sample time or saves states.
Do not use virtual buses as inputs or outputs to the referenced model when the referenced model uses the I/O arguments step method. When bus signals cross referenced model boundaries, either use nonvirtual buses or use the Default step method.
See Also
coder.mapping.api.CodeMappingCPP
| coder.mapping.api.get
| coder.mapping.utils.create
| find
| getClassName
| setClassName
| getClassNamespace
| setClassNamespace
| getData
| setData
| getFunction
| setFunction
Related Examples
- Configure C++ Class Interface for Rate-Based Models
- Configure C++ Class Interface for Export-Function Models