Main Content

C Function

Integrate and call external C/C++ code from a Simulink model

Since R2020a

  • C Function block

Libraries:
Simulink / User-Defined Functions

Description

The C Function block integrates and calls external C/C++ code from a Simulink® model. Use this block to define external code and customize the integration of your code by preprocessing or postprocessing the data. In addition, you can specify customized code for simulation and C code generation. You can conditionally call functions defined in your code, and you can also call multiple functions in one block. Using this block, you can initialize persistent data and pass it to an external function.

The C Function block supports initializing persistent data and calling external functions from the block dialog box. Persistent data can include an object of a C++ class defined in your custom code. See Interface with C++ Classes Using C Function Block. The block supports only initializing and terminating persistent data. The block does not support updating the data during simulation. To model a dynamic system with continuous states, use an S-Function block. To learn more about S-functions, see What Is an S-Function?

Define the source code and supporting files to be called by the C Function block in the Simulation Target pane of the Model Configuration Parameters dialog box. See Model Configuration Parameters: Simulation Target.

Note

C99 is the standard version of C language supported for custom C code integration into Simulink.

Call C Library Functions

You can call these C Math Library functions directly from the C Function block.

absacosasinatanatan2ceil
coscoshexpfabsfloorfmod
labsldexploglog10powsin
sinhsqrttantanh  

When you call these functions, double precision applies unless all the input arguments are explicitly single precision. When a type mismatch occurs, a cast of the input arguments to the expected type replaces the original arguments. For example, if you call the sin function with an integer argument, a cast of the input argument to a floating-point number of type double replaces the original argument.

To call other C library functions, create and call an external wrapper function that calls the C library function.

Call the abs, fabs, and labs Functions

Interpretation of the abs, fabs, and labs functions in C Function block goes beyond the standard C version to include integer and floating-point arguments:

  • If x is an integer, the standard C function abs applies to x, or abs(x).

  • If x is a double, the standard C function labs applies to x, or labs(x).

  • If x is a single, the standard C function fabs applies to x, or fabs(x).

Code Replacement Library (CRL) Based on Type

The call to the function should call the correct CRL based on the type of data passed into the function. If no CRL is specified, the call to the function should call to type-specific library. The CRL for C99 generates a type-specific function. For example:

Type passed inCode generation call
sin(doubleIn)sin(doubleIn)
sin(floatIn)sinf(floatIn)

Limitations

Limitations apply when using these Simulink features with the C Function block.

  • Simulink Coverage™

    Only execution coverage of the C Function block is measured.

  • Simulink Design Verifier™

    Simulink Design Verifier does not generate test cases for coverage objectives inside the C Function block. The limitations that apply to C/C++ S-functions also apply to C/C++ code in a C Function block. In particular, calls to external or library functions are replaced by stubs for analysis. For more information on these limitations, see Support Limitations and Considerations for S-Functions and C/C++ Code (Simulink Design Verifier).

  • Simulink Code Inspector™

    Simulink Code Inspector does not inspect the code generated from the C Function block.

These limitations apply to the C code that you specify in a C Function block.

  • Local static variables using the static keyword are not supported. To cache values across time steps, define a symbol as Persistent in the Symbols table of the block dialog box.

  • You cannot #include files in the code. Files containing external functions must be specified in the Simulation Target pane of the Configuration Parameters window.

  • Taking the address of a Constant symbol is not supported.

  • Directly calling C library functions other than the C Math Library functions listed above under Call C Library Functions is not supported. To call other C library functions, create and call a wrapper function that calls the C library function.

Ports

Input

expand all

The number of input ports is determined by the number of symbols with Input or InputOutput scope defined in the Symbols table in the block parameters dialog box. Each input port label is the same as the name of the Input or InputOutput symbol unless you change it by editing the Label field in the Symbols table of the block dialog box.

Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | Boolean | enumerated | bus | fixedpoint

Output

expand all

The number of output ports is determined by the number of symbols with Output or InputOutput scope defined in the Symbols table in the block parameters dialog box. Each output port label is the same as the name of the Output or InputOutput symbol unless you change it by editing the Label field in the Symbols table of the block dialog box.

Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | Boolean | enumerated | bus | fixedpoint

Parameters

expand all

Output code that the block executes at each time step during simulation, specified as a character vector or string scalar. For example, you can call a function from external C code, make modifications to the results, and perform operations to pass the results to other blocks.

Programmatic Use

Block Parameter: OutputCode
Type: character vector or string scalar
Value: "" | C code
Default: ""

Initialization code that the block executes one time at the start of simulation, specified as a character vector or string scalar. For example, you can initialize persistent symbols.

Programmatic Use

Block Parameter: StartCode
Type: character vector or string scalar
Value: "" | C code
Default: ""

Reinitialization code for the block to execute when enabling a subsystem or model in which the block is placed, specified as a character vector or string scalar. The code executes one time at the start of simulation, and if the block is inside a subsystem or model containing an Enable block with the States when enabling parameter set to reset, the code also executes each time the subsystem or model switches from disabled to enabled. See Using Enabled Subsystems. You can use this code, for example, to set an initial output value or reset the value of a persistent variable.

Programmatic Use

Block Parameter: InitializeConditionsCode
Type: character vector or string scalar
Value: "" | C code
Default: ""

Termination code that the block executes one time at the end of simulation, specified as a character vector or string scalar. For example, use this code to free the memory cached on persistent symbols specified as void pointers.

Programmatic Use

Block Parameter: TerminateCode
Type: character vector or string scalar
Value: "" | C code
Default: ""

Symbols and symbol properties used in the C code, specified as a table. You must enter the following attributes of each symbol in the table:

  • Name — Symbol name in the code.

    If the symbol represents a C++ class object, the Name field serves as a call to the class constructor:

    ObjectName(Argument1,Argument2,...)

  • Scope — Scope of the symbol. These scopes are available:

    • Input — Input to the block.

    • Output — Output to the block.

    • InputOutput — Both input and output to the block.

      Use the InputOutput scope to map an input passed by a pointer in your C code. Ports created using an InputOutput scope have the same name for input and output ports. InputOutput scope enables buffer reuse for input and output ports. Buffer reuse may optimize memory use and improve code simulation and code generation efficiency, depending on the signal size and the block layout. Limitations include:

      • An InputOutput symbol cannot be used in Start Code, Initialize Conditions Code, or Terminate Code.

      • InputOutput symbols do not support the void* data type.

      • InputOutput symbols do not support size() expressions.

    • Parameter — Block parameter that appears on the block parameter mask. The parameter name is defined by the Label of the symbol.

    • Persistent — Persistent block data, which retains its value from one time step to the next during simulation.

      You can define a void pointer using the Persistent scope. A void pointer is a pointer that can store any type of data that you create or allocate.

      You can instantiate an object of a C++ class defined in your custom code by defining a symbol with Persistent scope and using Class: ClassName as the Type for the symbol. See Interface with C++ Classes Using C Function Block.

    • Constant — Constant value, defined using value-size or numeric expressions.

  • Label — Label of the symbol. For a symbol with Input, InputOutput, or Output scope, the label appears as the port name on the block. For a symbol with Parameter scope, the label appears on the block parameter mask. If the scope is Constant, the label is the constant expression. You cannot define a label for Persistent scope symbols.

  • Type — Data type of the symbol. Select a data type from the drop-down list or specify a custom data type.

    C++ class types defined in your custom code are supported, as are Simulink.Bus, Simulink Enum, and Simulink.AliasType types. Enter the Type as shown in this table.

    Custom typeSpecification in Type field
    C++ classClass: C++ClassName
    Simulink.BusBus: BusTypeName
    Simulink.EnumEnum: EnumTypeName
    Simulink.AliasTypeAliasTypeName

  • Size — Size of the symbol data. You can use a size expression to define the size of an output or use -1 to inherit size.

  • Port — Port index of the symbol. For an Input, InputOutput, or Output symbol, Port specifies the port index on the block of the port or ports corresponding to the symbol. For a Parameter symbol, Port specifies the order that the symbol appears in the block parameter mask.

Programmatic Use

Block Parameter: SymbolSpec
Type: SymbolSpec object
Value: SymbolSpec object
Default: Empty array of Symbol objects

Sample period, specified in seconds. See Types of Sample Time and Specify Sample Time. If the block defines persistent symbols, you cannot specify a continuous sample time.

Programmatic Use

Block Parameter: SampleTime
Type: string scalar or character vector
Default: "-1"

Block Characteristics

Data Types

Booleana | busa | doublea | enumerateda | fixed pointa | integera | singlea

Direct Feedthrough

no

Multidimensional Signals

yes

Variable-Size Signals

no

Zero-Crossing Detection

no

a Actual data type or capability support depends on block implementation.

Extended Capabilities

Version History

Introduced in R2020a