Main Content

Generate C++ Class Interface from Multi-Instance Export-Function Model

This example shows you how to configure an export-function model that calls the same independent algorithm multiple times to generate reentrant, multi-instance C++ class code. When you configure the code interface packaging for a model to produce a C++ class interface, the model algorithm and associated data are generated as an encapsulated C++ class. The entry-point step function for the model is a method of the class, and it operates directly on data members of the class.

After reviewing the model and configuration settings, generate code, and then review the generated code.

Open the Model and Review Configuration

Open the export-function model CppMultiInstance. The model contains two Model blocks named CppEventCounterA and CppEventCounterB that each reference the model named CppEventCounter.

model='CppMultiInstance';
open_system(model);

Image of CppMultiInstance contains two instances of model CppEventCounter.

You can verify that the model is designated as an export-function model by using the Property Inspector. Open the Property Inspector, select the Execution tab, and verify Set execution domain is selected and Domain is set to Export function.

The model domain is specified as Export function under the Execution tab of the Property Inspector.

Examine Relevant Model Configuration Parameter Settings

Verify the configuration settings for the top model CppMultiInstance.

1. Open the Embedded Coder app.

2. Open the Model Configuration Parameters dialog box.

3. Open the Solver pane and specify the configuration settings required for generating code from export-function models.

  • Set Type to Fixed-step.

  • Set Solver to auto (Automatic solver selection) or discrete (no continuous states).

  • Set Periodic sample time constraint to Unconstrained.

4. Open the Code Generation pane. Under Target selection, confirm that Language is set to C++.

5. Open the Code Generation > Interface pane.

  • Code interface packaging is set to C++ class. This parameter setting is required to instruct the code generator to produce a C++ class interface.

  • Setting Code interface packaging to C++ class enables you to set the parameter Multi-instance code error diagnostic. For this example, this parameter is set to Error, indicating that the code generator aborts if the model violates requirements for generating multi-instance code.

  • Remove error status field in real-time model data structure is selected. Selecting this parameter specifies whether to omit the error status field from the generated real-time model data structure rtModel, which results in more compact generated code if the error status is not needed.

  • Include model types in model class is selected. Selecting this parameter specifies to nest struct types in the body of the model class definition.

  • Under Advanced parameters, the parameter Use dynamic memory allocation for model block instantiation is not selected. This parameter is cleared by default, which results in a parent model maintaining information about its referenced models, including its direct and indirect children. If you select this parameter, the code generator uses dynamic memory allocation to instantiate objects for referenced models using the new operator.

For additional information about workflows and other requirements for export-function modeling, see Export-Function Models Overview.

The configuration parameter settings for the referenced model CppEventCounter are the same as for the top-model CppMultiInstance.

Configure Data Mappings

When generating code for this model, the class definition of the model encapsulates the inports, outports, model parameters, signals, states, and internal data. You can specify the visibility and access method for the data members by using the Code Mappings editor. See Code Mappings – C++ Editor.

For this example:

  • Outports are defined as public members, accessed by an inlined, structure-based method.

  • Model parameter arguments are private members, accessed by an aggregate structure-based get and set method.

  • Model parameters, signals, states, and internal data are public members.

To view the code mappings, in the Embedded Coder toolbar, select Code Interface > Code Mappings. Data mappings are located under the Data tab.

For detailed information about configuring data members, see Interactively Configure C++ Interface and Configuring Parameters for C++ Class Code Generation.

Configure Entry-Point Method Mappings

The model class also encapsulates entry-point methods in the generated code. You can specify the names of entry-point methods by using the Code Mapping editor. Method name mappings are located under the Functions tab.

In the generated code, each root-level function-call Inport block generates an entry-point method. For this example:

  • The exported function on the Input block eventA is renamed to inputEventA.

  • The exported function on the Input block eventB is renamed to inputEventB.

  • Initialize and Terminate methods keep their default names.

Review the Referenced Model

Double-click CppEventCounter to open the referenced model. The referenced model includes a Function-Call Subsystem that contains the algorithm triggered by input method calls.

The image shows the model CppEventCounter containing a Function-Call Subsystem and displays the contents of the Function-Call Subsystem, which consists of an event counter algorithm.

The model functions as an event counter and consists of a Trigger block (function), a Bias block (Index), a Unit Delay block, and an Output port. The Trigger block has Trigger type set to function-call, which causes the model to execute when the control port receives a function-call event.

The configuration settings and data mappings for the referenced model CppEventCounter are the same as for the top-model CppMultiInstance. The algorithm step method is named counterStep.

Generate and Review Code

slbuild(model);
### Searching for referenced models in model 'CppMultiInstance'.
### Found 1 model references to update.
### Starting serial model reference code generation build.
### Starting build procedure for: CppEventCounter
### Successful completion of build procedure for: CppEventCounter
### Starting build procedure for: CppMultiInstance
### Successful completion of build procedure for: CppMultiInstance

Build Summary

Code generation targets built:

Model            Action                        Rebuild Reason                       
====================================================================================
CppEventCounter  Code generated and compiled.  CppEventCounter.cpp does not exist.  

Top model targets built:

Model             Action                        Rebuild Reason                                    
==================================================================================================
CppMultiInstance  Code generated and compiled.  Code generation information file does not exist.  

2 of 2 models built (0 models already up to date)
Build duration: 0h 0m 24.032s

The code generator places model-specific generated files for the model CppMultiInstance in the folder CppMultiInstance_ert_rtw and shared files in folder slprj. Generated files for the reference model CppEventCounter are located in the shared folder in slprj/ert/CppEventCounter.

The code generator creates a model-specific class for each model. Objects of the model class for each referenced model are created in the top model definition, where each object is stored as a data member of the parent model class.

Inspect Generated Class Definition for Multi-Instance Referenced Model

The code generator places model class definitions in the model.h file for the referenced model. For this example, the code generator places the class definition for CppEventCounter in the file slprj/ert/CppEventCounter/CppEventCounter.h.

Review the class definition for CppEventCounter.

  • The block state for the unit delay is declared in public structure DW_CppEventCounter_T.

  • The event export function is declared as the public method counterStep, as configured in the code mappings for the referenced model.

class CppEventCounter final
{
 public:
  // Block states (default storage) for model 'CppEventCounter'
  struct DW_CppEventCounter_T {
    real_T UnitDelay_DSTATE;           // '<S1>/Unit Delay'
  };

  ...

  // model step function
  void counterStep(real_T *rty_Outport);

  // Block states
  DW_CppEventCounter_T CppEventCounter_DW;

  // Constructor
  CppEventCounter();

  // Destructor
  ~CppEventCounter();
};

The class name defaults to the model name. You can customize the class name and namespace by selecting Code Interface > Class Name & Namespace. For more information, see Interactively Configure C++ Interface.

Inspect Generated Algorithm Code for Multi-Instance Referenced Model

The code generator places the algorithm code in the model.cpp file for the referenced model. For this example, the code generator places code for model CppEventCounter in the file slprj/ert/CppEventCounter/CppEventCounter.cpp.

#include "CppEventCounter.h"
#include "rtwtypes.h"

void CppEventCounter::counterStep(real_T *rty_Out1)
{
  *rty_Out1 = CppEventCounter_DW.UnitDelay_DSTATE;

  CppEventCounter_DW.UnitDelay_DSTATE = *rty_Out1 + 1.0;
}
...

Inspect Generated Class Definition for Top Model

For the top model, the code generator defines the model class CppMultiInstance in the file CppMultiInstance_ert_rtw/CppMultiInstance.h.

Review the class definition for CppMultiInstance.

  • Outputs are declared in public structure ExtY_CppMultiInstance_T and can be accessed by using the inlined method getExternalOutputs.

  • Entry-point methods initialize, inputEventA, inputEventB, and terminate are declared as public methods.

  • Instances of type CppEventCounter are declared as private members of CppMultiInstance.

class CppMultiInstance final
{
 public:
  // External outputs (root outports fed by signals with default storage)
  struct ExtY_CppMultiInstance_T {
    real_T countA;                     // '<Root>/countA'
    real_T countB;                     // '<Root>/countB'
  };

  ...

  // External outputs
  ExtY_CppMultiInstance_T CppMultiInstance_Y;

  // Root outports get method
  const ExtY_CppMultiInstance_T &getExternalOutputs() const
  {
    return CppMultiInstance_Y;
  }
  
  // model initialize function
  void initialize();

  // model step function
  void inputEventA();

  // model step function
  void inputEventB();

  // model terminate function
  static void terminate();

  ...

 private:
  // model instance variable for '<Root>/CppEventCounterA'
  CppEventCounter CppEventCounterAMDLOBJ1;

  // model instance variable for '<Root>/CppEventCounterB'
  CppEventCounter CppEventCounterBMDLOBJ2;
  
  ...
}

Code generation controls the naming of class objects based on the model construction. Object names, such as CppEventCounterAMDLOBJ1 and CppEventCounterBMDLOBJ2 in this example, cannot be customized.

Inspect Generated Entry-Point Methods for Top Model

The code generator places the entry-point method code for the top model CppMultiInstance in the file CppMultiInstance_ert_rtw/CppMultiInstance.cpp.

In the generated code, each root-level function-call Inport block calls an instance-specific entry-point method.

#include "CppMultiInstance.h"
#include "CppEventCounter.h"

// Model step function
void CppMultiInstance::inputEventA()
{
  CppEventCounterAMDLOBJ1.counterStep(&CppMultiInstance_Y.countA);
}

void CppMultiInstance::inputEventB()
{
  CppEventCounterBMDLOBJ2.counterStep(&CppMultiInstance_Y.countB);
}

// Model initialize function
void CppMultiInstance::initialize() 
{
...
}

Close Models

Close the model and the code generation report.

bdclose(model)

See Also

|

Related Topics