Control Data and Function Interface in Generated Code
To use the code that you generate from a model, you call generated entry-point functions
such as step
and initialize
. The calling environment and
the generated functions exchange input and output data through global variables or through
formal parameters (arguments). This data and the exchange mechanisms constitute the interfaces
of the entry-point functions. For information about the default interfaces for reentrant and
nonreentrant models in the generated code, see How Generated Code Exchanges Data with an Environment.
By controlling the interfaces that appear in the generated code, you can:
Minimize the modifications that you must make to existing code.
Generate stable interfaces that do not change or minimally change when you make changes to the model.
Generate code that exchanges data more efficiently (for example, by using pointers and pass-by-reference arguments for nonscalar data).
Control Type Names, Field Names, and Variable Names of Standard I/O Structures (Embedded Coder)
By default, for nonreentrant code, Inport blocks at the root level of the model appear in the generated code as fields of a global structure variable. Similarly, Outport blocks appear in a different structure. For reentrant code, depending on your setting for model configuration parameter Pass root-level I/O, the code generator can also package input and output data into standard structures.
With Embedded Coder®, you can control these names. See Manage Replacement of Simulink Data Types in Generated Code.
Control Names of Generated Entry-Point Functions (Embedded Coder)
To use the generated code, you write code that calls generated entry-point functions.
For example, entry-point functions include
,
model
_step
, and top-level functions
generated from an export-function model. To control the names of the model entry-point
functions, use the Code Mappings editor (requires Embedded Coder) to apply a combination of these techniques:model
_initialize
On the Function Defaults tab, specify default naming rules for categories of entry-point functions by applying function customization templates in the Code Mappings editor. With this technique, a naming rule applies to functions in a category. For more information, see Configure Default Code Generation for Functions.
On the Functions tab, specify names for individual entry-point functions by either directly editing the Function Name column or through a configuration dialog box opened from the Function Preview column. Names that you specify override default naming rules specified by function customization templates. For more information, see Configure Generated C Function Interface for Model Entry-Point Functions
Control Data Interface for Nonreentrant Code
When you set the model configuration parameter Code interface
packaging to Nonreusable function
(the default),
generated entry-point functions are not reentrant. Typically, the functions exchange data
with the calling environment through direct access to global variables.
Configure Inport or Outport Block as Separate Global Variable
To remove the block from the standard I/O structures by creating a separate global
variable, apply a storage class, such as ExportedGlobal
or
ExportToFile
, to the signal that the block represents. You can
configure a default storage class for categories of data elements, such as
Inport blocks. As you add such blocks to the model, they acquire the
storage class that you specify. You can use the Code Mappings editor also to configure
individual blocks. You might do this if a model has just a few data elements of a specific
category or override the default configuration settings.
For an example, see Design Data Interface by Configuring Inport and Outport Blocks. For general information about configuring data for code generation, see C Data Code Interface Configuration for Model Interface Elements.
Configure Generated Code to Read or Write to Global Variables Defined by External Code
If your calling code already defines a global variable that you want the generated
code to use as input data or use to store output data, you can reuse the variable by
preventing the code generator from duplicating the definition. Apply a storage class to
the corresponding Inport or Outport block in the model.
Choose a storage class that specifies an imported data scope, such as
ImportedExtern
or ImportFromFile
. For information
about applying storage classes, see C Data Code Interface Configuration for Model Interface Elements and Organize Parameter Data into a Structure by Using Struct Storage Class.
Package Multiple Inputs or Outputs into Custom Structure
You can configure a single Inport or Outport block to appear in the generated code as a custom structure that contains multiple input or output signals. You can also configure the block to appear as a substructure of the default I/O structures or as a separate structure variable.
Configure the block as a nonvirtual bus by using a Simulink.Bus
object as the data type of the block. If your external code defines the structure type,
consider using the Simulink.importExternalCTypes
function to generate
the bus object.
To generate the bus as a substructure in the standard I/O structures, leave the block storage class at the default setting,
Auto
. If you have Embedded Coder, in the Code Mappings editor, on the Data Defaults tab, set the storage class for categories Inports and Outports toDefault
.To generate the bus as a separate global structure variable, apply a storage class such as
ExportedGlobal
orExportToFile
.
For more information about grouping signals into custom structures in the generated code, see Organize Data into Structures in Generated Code.
Configure Inport or Outport Block as Function Call (Embedded Coder)
If your external code defines a function that returns input data for the generated
code or accepts output data that the generated code produces, you can configure an
Inport or Outport block so that the generated code calls
the function instead of accessing a global variable. Apply the Embedded Coder storage class GetSet
. For more information, see Access Data Through Functions with Storage Class GetSet.
Pass Inputs and Outputs Through Function Arguments (Embedded Coder)
With Embedded Coder, you can optionally configure the model step (execution) function to access root-level input and output through arguments instead of directly reading and writing to global variables. Completely control the argument characteristics such as name, order, and passing mechanism (by reference or by value). This level of configuration can help to integrate generated code with your external code.
To pass inputs and outputs through arguments, in the Configure C Step Function interface dialog box, select Configure arguments for Step function prototype. Each Inport and Outport block at the root level of the model appears in the code as an argument of the execution function. For more information, see Configure Generated C Function Interface for Model Entry-Point Functions.
Configure Referenced Model Inputs and Outputs as Global Variables (void-void
)
By default, for a nonreentrant referenced model, the generated code passes root-level
input and output through function arguments. A nonreentrant referenced model is one in
which you set model configuration parameter Total number of instances allowed
per top model to One
.
To pass this data through global variables instead (for a void-void
interface), in the referenced model, apply storage classes such as
ExportedGlobal
and ExportToFile
to root-level
Inport and Outport blocks.
To apply a default storage class to such blocks, use the Code Mapping Editor. With this technique, as you add such blocks to the model, the blocks acquire the default storage class, preserving the
void-void
interface. For more information, see Configure Default Code Generation for Data.To override the default storage class, apply storage classes directly to individual blocks by using the Code Mapping editor. See C Data Code Interface Configuration for Model Interface Elements.
For an example that requires Embedded Coder, see Establish Data Ownership in a Model Hierarchy.
Control Data Interface for Reentrant Code
When you set Code interface packaging to Reusable
function
, generated entry-point functions are reentrant. The functions
exchange data with the calling environment through formal parameters (arguments). By
default, each root-level Inport and Outport block appears in
the generated code as a separate argument instead of a field of the standard I/O
structures.
To reduce the number of arguments, see Reduce Number of Arguments by Using Structures.
To control the data types of the arguments, see Control Data Types of Arguments.
Prevent Unintended Changes to the Interface
Some changes that you make to a model change the entry-point function interfaces in the generated code. For example, if you change the name of the model, the names of the functions can change. If you configure the model code to exchange data through arguments, when you add or remove Inport or Outport blocks or change the names of the blocks, the corresponding arguments can change.
For easier maintenance of your calling code, prevent changes to the interfaces of the entry-point functions.
If you exchange input and output data through arguments, configure the generated code to package Inport and Outport blocks into structures instead of allowing each block to appear as a separate argument (the default). Then, when you add or remove Inport or Outport blocks, or change their properties such as name and data type, the fields of the structures change, but the function interfaces do not change. See Reduce Number of Arguments by Using Structures.
Set the data types of Inport and Outport blocks explicitly instead of using an inherited data type setting (which these blocks use by default). Inherited data type settings can cause the blocks to use different data types depending on the data types of upstream and downstream signals. For more information about configuring data types, see Control Data Types of Signals.
With Embedded Coder, specify function names that do not depend on the model name. If you specify a naming rule with a function customization template, do not use the token
$R
in the rule. See Control Names of Generated Entry-Point Functions (Embedded Coder).
Reduce Number of Arguments by Using Structures
Reducing the number of arguments of a function can improve the readability of the code and reduce consumption of stack memory. To create a structure argument that can pass multiple pieces of data at one time, use these techniques:
Manually combine multiple Inport or Outport blocks so that they appear in the generated code as fields of a structure or substructure of a standard data structure. The generated entry-point function or functions accept the address of the structure as a separate argument or as a substructure (field) of the standard I/O structures.
Replace the Inport or Outport blocks with a single block, and configure the new block as a nonvirtual bus by using a
Simulink.Bus
object as the data type of the block. If your external code defines the structure type, consider using theSimulink.importExternalCTypes
function to generate the bus object. See Organize Data into Structures in Generated Code andSimulink.importExternalCTypes
.When you generate reentrant code with Embedded Coder, configure Inport and Outport blocks to appear in aggregated structures by default. Set model configuration parameter Pass root-level I/O as to a setting other than
Individual arguments
.To package Inport and Outport blocks into the real-time model data structure, select
Part of model data structure
. The code generator aggregates the blocks into the default I/O structures to which the real-time model data structure points. The generated entry-point function or functions accept the real-time model data structure as a single argument. If you choose this setting, the function has the smallest number of arguments.To aggregate Inport blocks into a structure and Outport blocks into a different structure, select
Structure reference
. The generated entry-point function or functions accept the address of each structure as an argument. Another argument accepts the real-time model data structure. If you choose this setting, the inputs and outputs are more identifiable in the function interfaces.With this setting, if you remove the root-level Inport blocks or the root-level Outport blocks, the function signature can change. Similarly, the signature can change if you add a root-level Inport or Outport block to a model that does not include such blocks.
For more control over the characteristics of the structures, set Pass root-level I/O as to
Part of model data structure
. Then, set the default storage class for Inport and Outport blocks to a structured storage class that you create. With this technique:You can create a single structure for the blocks or create two separate structures.
You can control the names of the structure types.
The structures appear as substructures of the real-time model data structure. You must set Pass root-level I/O as to
Part of model data structure
.
Create the storage class by using the Embedded Coder Dictionary (see Define Service Interfaces, Storage Classes, Memory Sections, and Function Templates for Software Architecture). Apply the storage class by using the Code Mappings editor (see Configure Default Code Generation for Data).
For more information, see Pass root-level I/O as.
Control Data Types of Arguments
You can configure the generated entry-point functions to exchange data through
arguments. For a scalar or array argument, to control the name of the primitive data type,
use a Simulink.AliasType
object to either set the data type of the
corresponding block or to configure data type replacements for the entire model. These
techniques require Embedded Coder. For more information, see Manage Replacement of Simulink Data Types in Generated Code.
Promote Data Item to the Interface
By default, the code generator assumes that Inport and Outport blocks at the root level of the model constitute the data interface of the model. You can promote an arbitrary signal, block parameter, or block state to the interface so that other systems and components can access it. See Promote Internal Data to the Interface.
Related Topics
- Design Data Interface by Configuring Inport and Outport Blocks
- Define Interfaces of Model Components
- Analyze Generated Data Code Interface Report
- Configure Generated C Function Interface for Model Entry-Point Functions
- How Generated Code Exchanges Data with an Environment
- Exchange Data Between External C/C++ Code and Simulink Model or Generated Code
- Configure Generated Code According to Interface Control Document Specifications
- C Data Code Interface Configuration for Model Interface Elements