Main Content

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 FunctionMechanism to Exchange Data with ModelExamples 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 coder.ceval, see Integrate C Code by Using the MATLAB Function Block. For information about creating data items in a MATLAB Function block (which you can pass to your function as arguments), see Create and Define MATLAB Function Block Variables.

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 ConstructExample C CodeSimulink EquivalentMore Information

Primitive type alias (typedef)

typedef float mySinglePrec_T;

Create a Simulink.AliasType object. Use the object to:

  • Set the data types of signals and block parameters in a model.

  • Configure data type replacements for code generation.

Generating code that uses an alias data type requires Embedded Coder®.

For information about defining custom data types for your model, see Simulink.AliasType and Manage Replacement of Simulink Data Types in Generated Code (Embedded Coder).

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 Simulink.LookupTable.

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 Simulink.Bus object that corresponds to your structure type.

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 Simulink.Parameter) that stores a MATLAB structure. Use the bus object as the data type of the parameter object.

To package lookup table data into a structure, use Simulink.LookupTable and, optionally, Simulink.Breakpoint objects.

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, Simulink.LookupTable.

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 ConstructExample C CodeSimulink EquivalentMore Information

Macro

#define myParam 9.8

Apply the storage classes Define and ImportedDefine to parameters. With macros, you can reuse a parameter value in multiple locations in an algorithm and change the parameter value between code compilations without consuming memory to store the value. Typically, macros represent engineering constants that you do not expect to change during code execution.

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 Const, Volatile, and ConstVolatile to data items.

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

  • Apply the storage class BitField to signals, states, and parameters whose data type is boolean, fixed-point, or integer.

  • Use a model configuration parameter to aggregate Boolean data into bit fields.

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 GetSet to signals, states, and parameters. Each data item appears in the generated code as a call to your custom functions that read and write to the target data.

This technique requires Embedded Coder.

Access Data Through Functions with Storage Class GetSet (Embedded Coder)

Considerations for Other Modeling Goals

GoalConsiderations 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:

  • At the time that you begin an external mode simulation, the external executable uses the value that your code uses to initialize the parameter data. However, when you change the corresponding value in Simulink during the simulation (for example by modifying the Value property of the corresponding parameter object), Simulink downloads the new value to the executable.

  • SIL and PIL simulations do not import the parameter value from your code. Instead, the simulations use the parameter value from Simulink. If you include your external code in the Simulink Coder™ build process, duplicate data definitions can prevent the generated code from compiling.

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