Main Content

Integrate External C/C++ Code into Simulink Using C Function Blocks

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, Start, Initialize Conditions, and Terminate panes in the block parameters dialog. Use the C Function block to:

  • Call functions from external C code including functions defined under namespace, 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.

Note

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

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 */
        const 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. Create a new, blank model and 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 box.

  3. Define the custom header and source files.

    • Define header file — In the block dialog box, click the arrow next to the Configure custom code settings button and select Use Configuration Parameters Custom Code. Then click the button to open the Configuration Parameters dialog box and specify the file names in the Include headers field in the Code information tab of the Simulation Target pane. (since R2024a)

      Specify custom header file in model Configuration Parameters dialog box. The following text is entered in the field: #include "data_array.h".

      Before R2024a: Click the Configure custom code settings button and specify the file names in the Include headers field in the Code information tab of the Simulation Target pane. For more information, see Specify and Configure Custom C/C++ Code.

    • Define source file — In the block dialog box, click the arrow next to the Configure custom code settings button and select Use Configuration Parameters Custom Code. Then click the button to open the dialog box and specify the file names in the Source files field in the Code information tab of the Simulation Target pane. (since R2024a)

      Specify custom source file in Configuration Parameters dialog box. The following text is entered in the field: data_array.c.

      Before R2024a: Click the Configure custom code settings button and specify the file names in the Source files field in the Code information tab of the Simulation Target pane. For more information, see Specify and Configure Custom C/C++ Code. To verify that your custom code can be parsed and built successfully, click Validate custom code.

  4. In the Output pane, under Simulation tab of the C Function block parameters dialog box, write the code that the block executes during simulation. In this example, the external C function computes a sum. In the Output 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[0];
    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 and Terminate panes.

  5. Use the Ports and Parameters table to define the symbols used in the code in the block. Add or delete a symbol using the Add and Delete buttons. Define all symbols used in the Output, Start, Initialize Conditions, and Terminate panes to ensure that ports display correctly.

    Use the Ports and Parameters table to specify the symbols.

    In the Ports and Parameters table, for each symbol used in the code in the block, define the Name, Scope, Label, Type, Dimensions, and Port, as appropriate.

    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.

    Add Constant block that provides the input data to the model.

Note

If a model has custom code, after the model is updated or run, the slprj folder may be locked due to the loaded custom code simulation executable file. You cannot delete the folder when it is locked. To unload the executable file and unlock the slprj folder, use the clear mex command. See clear.

Specify Simulation or Code Generation Code

For versions R2024a or later, if you need to specify different output codes for simulation and code generation, it is recommended that you use Use same code as simulation parameter from the block dialog box. To specify different output codes, clear the Use same code as simulation check box under the Code Generation tab and specify the output codes in the Output field under Simulation and Code generation tabs. For more information, see Use same code as simulation. This is an alternative method to specify different codes instead of using MATLAB_MEX_FILE. (since R2024a)

Before R2024a: You can specify different output codes for simulation and code generation for the C Function block by defining MATLAB_MEX_FILE in the Output Code field of the block dialog box. For example, to specify code that only runs during the model simulation, use the following.

#ifdef MATLAB_MEX_FILE
/* Enter simulation code */
#else 
/* Enter code generation code */
#endif

Specify Declaration for Target-Specific Functions for Code Generation

For versions R2024a or later, you need to declare headers files only if the Generate code as - is (optimizations off) check box in the Code generation tab of the block is unchecked. In such case, you can include a declaration with the correct signature in the Output field of the Simulation tab and generate code. (since R2024a)

Before R2024a: For code generation purposes, if you do not have the external header file with the declaration of a function (such as a target-specific device driver) that you want to call from the C Function block, you can include a declaration with the correct signature in the Output Code field of the block.

This action creates a function call to the expected function when code is generated, as in the following example:

#ifndef MATLAB_MEX_FILE
extern void driverFcnCall(int16_T in, int16_T * out);
driverFcnCall(blockIn, &blockOut);
#endif

See Also

Functions

Objects

Blocks

Related Topics