Call and Integrate External C Algorithms into Simulink

You can call and integrate your external C code into Simulink® models using C Function blocks. C Function blocks allow you to call external C code and customize the integration of your code using the Output Code, Start Code and Terminate Code panes in the block parameters dialog. Use C Function block to:

  • Call functions from external C code, and customize the code for your Simulink models.

  • Preprocess data to call a C function and postprocess data after calling the function.

  • Specify different code for simulation and code generation.

  • Call multiple functions.

  • Initialize and work with persistent data cached in the block.

  • Allocate and deallocate memory.

Use the C Function block to call external C algorithms into Simulink that you want to modify. To call a single C function from a Simulink model, use the C Caller block. To integrate dynamic systems that have continuous states or state changes, use the S-Function block.

The following examples use C Function blocks to calculate the sum and mean of inputs.

Write External Source Files

Begin by creating the external source files.

  1. Create a header file named data_array.h.

    /* Define a struct called DataArray */
    typedef struct DataArray_tag {
        /* Define a pointer called pData */
        double* pData;
        /* Define the variable length */
        int length;
    } DataArray;
    
    /* Function declaration */
    double data_sum(DataArray data);

  2. In the same folder, create a new file, data_array.c. In this file, write a C function that calculates the sum of input numbers.

    #include "data_array.h"
    
    /* Define a function that takes in a struct */
    double data_sum(DataArray data)
    {
        /* Define 2 local variables to use in the function */
        double sum = 0.0;
        int i;
        /* Calculate the sum of values */
        for (i = 0; i < data.length; i++) {
            sum = sum + data.pData[i];
        }
        /* Return the result to the block */
        return sum;
    }

Enter the External Code Into Simulink

  1. In a new, blank model, add a C Function block. The C Function block is in the User-Defined Functions library of the Library Browser.

  2. Double-click the C Function block to open the block dialog. Click to open the Configuration Parameters dialog. In the Simulation Target pane, define your header file under Insert custom C code in generated: > Header file.

  3. Define the source file under Additional build information > Source files.

    Click OK to close the Configuration Parameters.

  4. In the Output Code pane of the C Function block parameters dialog, write the code that the block executes during simulation. In this example, the external C function computes a sum. In the Output Code pane, write code that calls the data_array.c function to compute the sum, then computes the mean.

    /* declare the struct dataArr */
    DataArray dataArr;
    /* store the length and data coming in from the input port */
    dataArr.pData = &data;
    dataArr.length = length;
    
    /* call the function from the external code to calculate sum */
    sum = data_sum(dataArr);
    
    /* calculate the mean */
    mean = sum / length;

    You can specify code that runs at the start of a simulation and at the end of a simulation in the Start Code and Terminate Code panes.

  5. Use the Symbols table to define the symbols used in the external C code. Add or delete a symbol using the Add and Delete buttons. Define all symbols used in the Output Code, Start Code, and Terminate Code panes to ensure that ports display correctly.

    In the Symbols table, define the following.

    • Name — Symbol name in the source code.

    • Scope — Scope of the symbols and the order in which they appear. You can change the scope of a symbol at any time.

      • Input — Input symbol to the C Function block.

      • Output — Output symbol to the C Function block.

      • InputOutput — Define a symbol as both input and output to the C Function 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 the reuse of buffer for input and output ports. Reusing buffer may optimize memory use and improve code simulation and code generation efficiency, depending on the signal size and the block layout. Limitations include:

        • InputOutput symbol cannot be used in Start and Terminate code.

        • InputOutput port does not support void* data type.

        • InputOutput port does not support size() expressions.

      • Persistent — Define a symbol as persistent data.

        You can define a void pointer using the Persistent scope in the C Function block. A void pointer is a pointer that can store any type of data that you created or allocated.

      • Constant — Define a symbol as constant using value-size or numeric expressions.

      • Parameter — Define a symbol as parameter. The parameter name is defined by the Label of the symbol.

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

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

      To use a custom type such as Simulink.Bus, Simulink Enum or Simulink.AliasType that does not have an external header definition associated with a C Function block, set the type correctly on the Symbol table.

    • Size — Size of the symbol data. The C Function block supports only scalars and vectors are supported. Matrices and higher-dimension arrays are not supported. You can use a size expression to define the size of an output. Use -1 to inherit size.

    • Port — For input and output symbols, Port indicates the port index on the block of the symbol data. For parameter symbols, Port indicates the order that the symbol appears in the block parameter mask.

    Close the block parameters dialog. After filling in the data in the table, the C Function block now has one input port, and two output ports with the labels specified in the table.

  6. Add a Constant block to the Simulink canvas that will be the input to the C Function block. In the Constant block, create a random row array with 100 elements. To display the results, attach display blocks to the outputs of the C Function block.

Call C Library Functions From C Function Block

You can call this subset of the C Math Library functions 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.

If you want to call other C library functions that are not listed above, create an external wrapper function that calls the C library function.

Call the abs, fabs, and labs Function

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 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)

Specify Simulation or Code Generation Code

You can specify different output code for simulation and code generation for the C Function block by defining MATLAB_MEX_FILE. For example, to specify code that only runs during the model simulation, you use the following.

#ifdef MATLAB_MEX_FILE
/* Enter Sim Code */
#else 
/* Enter code generation code */
#endif

See Also

Functions

Objects

Blocks