Exchange Data Between External C/C++ Code and Simulink Model or Generated Code
Whether you import your external code into a Simulink® model or export the generated code to an external environment, the model or the generated code typically exchange data (signals, states, and parameters) with your code.
Functions in C or C++ code, including your external functions, can exchange data with a caller or a called function through:
Arguments (formal parameters) of functions. When a function exchanges data through arguments, an application can call the function multiple times. Each instance of the called function can manipulate its own independent set of data so that the instances do not interfere with each other.
Direct access to global variables. Global variables can:
Enable different algorithms (functions) and instances of the same algorithm to share data such as calibration parameters and error status.
Enable the different rates (functions) of a multitasking system to exchange data.
Enable different algorithms to exchange data asynchronously.
In Simulink, you can organize and configure data so that a model uses these exchange mechanisms to provide, extract, and share data with your code.
Before you attempt to match data interfaces, to choose an overall integration approach, see Choose an External Code Integration Workflow.
Import External Code into Model
To exchange data between your model and your external function, choose an exchange mechanism based on the technique that you chose to integrate the function.
To exchange data through the arguments of your external function, construct and configure your model to create and package the data according to the data types of the arguments. Then, you connect and configure the block that calls or represents your function to accept, produce, or refer to the data from the model.
For example, if you use the S-Function Builder to generate an S-Function block that calls your function, the ports and parameters of the block correspond to the arguments of the function. You connect the output signals of upstream blocks to the input ports and set parameter values in the block mask. Then, you can create signal lines from the output ports of the block and connect those signals to downstream blocks.
To exchange data through global variables that your external code already defines, a best practice is to use a Stateflow® chart to call your function and to access the variables. You write algorithmic C code in the chart so that during simulation or execution of the generated code, the model reads and writes to the variables.
To use such a global variable as an item of parameter data (not signal or state data) elsewhere in a model, you can create a numeric MATLAB® variable or
Simulink.Parameter
object that represents the variable. If you change the value of the C-code variable in between simulation runs, you must manually synchronize the value of the Simulink variable or object. If your algorithmic code (function) changes the value of the C-code variable during simulation, the corresponding Simulink variable or object does not change.If you choose to create a Simulink representation of the C-code variable, you can configure the Simulink representation so that the generated code reads and writes to the variable but does not duplicate the variable definition. Apply a storage class to the Simulink representation.
Technique for Integrating External Function | Mechanism to Exchange Data with Model | Examples and More Information |
---|---|---|
S-Function block |
Function arguments | To call your function through an S-function that you write or create by using the S-Function Builder , see S-Functions Incorporate Legacy C Code. |
C Function block | Function arguments | To call your function through a C Function block, see Integrate External C/C++ Code into Simulink Using C Function Blocks. |
C Caller block | Function arguments | To call your function through a C Caller block, see Integrate C Code Using C Caller Blocks. |
Stateflow chart |
Function arguments and direct access to global variables |
To call your function and access global variables in a Stateflow chart, see Access Custom Code Variables and Functions in Stateflow Charts (Stateflow). For information about creating data items in a chart (which you can pass to your function as arguments), see Add Stateflow Data (Stateflow). |
coder.ceval in MATLAB
Function block |
Function arguments | To call your function in a MATLAB Function
block by using |
Export Generated Code to External Environment
To export the generated code into your external code, see Exchange Data Between External Calling Code and Generated Code.
Simulink Representations of C Data Types and Constructs
To model and reuse your custom C data such as structures, enumerations, and
typedef
aliases, use the information in these tables.
Modeling Patterns for Matching Data in External C Code
C Data Type or Construct | Example C Code | Simulink Equivalent | More Information |
---|---|---|---|
Primitive type alias ( |
typedef float mySinglePrec_T; |
Create a
Generating code that uses an alias data type requires Embedded Coder®. |
For information about defining custom data types for your
model, see For an example that shows how to export the generated code into your external code, see Replace and Rename Simulink Coder Data Types to Conform to Coding Standards (Embedded Coder). |
Array |
int myArray[6]; | Specify signal and parameter dimensions as described in Determine Signal Dimensions. The generated code defines and accesses multidimensional data, including matrices, as column-major serialized vectors. If your external code uses a different format, consider using alternative techniques to integrate the generated code. See Code Generation of Matrices and Arrays. | For information about how the generated code stores nonscalar data (including limitations), see Code Generation of Matrices and Arrays. For an example that shows how to export the generated code into your external code, see Reuse Parameter Data in Different Data Type Contexts. To model lookup
tables, see |
Enumeration |
typedef enum myColorsType { Red = 0, Yellow, Blue } myColorsType; |
Define a Simulink enumeration that corresponds to your enumeration definition. Use the Simulink enumeration to set data types in a model. | To use enumerated data in a Simulink model, see Use Enumerated Data in Generated Code. For an example that shows how to generate enumerated parameter data, see Enumeration (Embedded Coder). For an example that shows how to export the generated code into your external code by exchanging enumerated data, see Exchange Structured and Enumerated Data Between Generated and External Code (Embedded Coder). |
Structure |
typedef struct myStructType { int count; double coeff; } myStructType; |
Create a To create structured signal or state data, package multiple signal lines in a model into a single nonvirtual bus signal. To create structured parameter data, create a parameter object
(such as To package lookup table data into a structure, use | For information about bus signals, see Group Signals or Messages into Virtual Buses. For information about structures of parameters, see Organize Related Block Parameter Definitions in Structures. For an example that shows how to import your external code into a model by using the Legacy Code Tool, see Integrate C Function Whose Arguments Are Pointers to Structures. For examples that show how to export the generated code into your external code, see Exchange Structured and Enumerated Data Between Generated and External Code (Embedded Coder) and Access Structured Data Through a Pointer That External Code Defines (Embedded Coder). To package
lookup table data into a structure, For general information about creating structures in the generated code, see Organize Data into Structures in Generated Code. |
Additional Modeling Patterns for Code Generation (Embedded Coder)
C Data Type or Construct | Example C Code | Simulink Equivalent | More Information |
---|---|---|---|
Macro |
#define myParam 9.8 | Apply the storage classes This technique requires Embedded Coder. | Macro Definitions (#define) (Embedded Coder) |
Storage type qualifiers such as const and
volatile |
const myParam = 9.8; | Apply the storage classes | Protect Global Data with Keywords const and volatile |
Bit field |
typedef struct myBitField { unsigned short int MODE : 1; unsigned short int FAIL : 1; unsigned short int OK : 1; } myBitField |
These techniques require Embedded Coder. | Bitfields (Embedded Coder) Optimize Generated Code by Packing Boolean Data into Bitfields (Embedded Coder) |
Call to custom external function that reads or writes to data |
External code:
/* Call this function to acquire the value of the signal. */ double get_inSig(void) { return myBigGlobalStruct.inSig; } Generated algorithmic code:
algorithmInput = get_inSig(); | Apply the storage class This technique requires Embedded Coder. | Access Data Through Functions with Storage Class GetSet (Embedded Coder) |
Considerations for Other Modeling Goals
Goal | Considerations and More Information |
---|---|
Use Simulink to run and interact with the generated code | You can use SIL, PIL, and external mode simulations to connect your model to the corresponding generated application for simulation. When you import parameter data from your external code:
For information about SIL and PIL, see Choose a SIL or PIL Approach (Embedded Coder). For information about external mode simulation, see External Mode Simulations for Parameter Tuning, Signal Monitoring, and Code Execution Profiling. |
Generate code comments that describe attributes of exported data including physical units, real-world initial value, and data type | Generating these comments can help you match data interfaces while handwriting integration code. See Add Custom Comments for Variables in the Generated Code (Embedded Coder). |
Related Topics
- How Generated Code Exchanges Data with an Environment
- Generate Code That Matches Appearance of External Code
- Design Data Interface by Configuring Inport and Outport Blocks
- Configure Generated Code According to Interface Control Document Specifications (Embedded Coder)
- Generate Code That Dereferences Data from a Literal Memory Address (Embedded Coder)