Main Content

External C Functions

This example shows several methods for integrating legacy C functions into generated code. These methods create an S-function or make a call to an external C function. For more information on S-functions, see S-Functions and Code Generation.

C Construct

extern double add(double, double);

#include "add.h"
double add(double u1, double u2)
{
   double y1;
   y1 = u1 + u2;
   return (y1);
}

Create S-Functions by Using Legacy Code Tool

Use the Legacy Code Tool to create an S-function and generate a TLC file. The code generation software uses the TLC file to generate code from this S-function. The advantage to using the Legacy Code Tool is that the generated code is fully inlined and does not need wrapper functions to access the custom code.

1. Create a C header file named add.h that contains the function signature:

extern double add(double, double);

2. Create a C source file named add.c that contains the function body:

double add(double u1, double u2)
{
   double y1;
   y1 = u1 + u2;
   return (y1);
}

3. To build an S-function for use in simulation and code generation, run the following script or execute each of these commands at the MATLAB® command line:

%% Initialize legacy code tool data structure
def = legacy_code('initialize');

%% Specify Source File
def.SourceFiles = {'add.c'};

%% Specify Header File
def.HeaderFiles = {'add.h'};

%% Specify the Name of the generated S-function
def.SFunctionName = 'add_function';

%% Create a c-mex file for S-function
legacy_code('sfcn_cmex_generate', def);

%% Define function signature and target the Output method
def.OutputFcnSpec = ['double y1 = add(double u1, double u2)'];

%% Compile/Mex and generate a block that can be used in simulation
legacy_code('generate_for_sim', def);

%% Create a TLC file for Code Generation
legacy_code('sfcn_tlc_generate', def);

%% Create a Masked S-function Block 
legacy_code('slblock_generate', def);
### Start Compiling add_function
    mex('-I/tmp/Bdoc24a_2528353_1407918/tp78c6b26e/ecoder-ex61094511', '-c', '-outdir', '/tmp/Bdoc24a_2528353_1407918/tp282a3288_c57d_42e2_9f63_c40ee67fac87', '/tmp/Bdoc24a_2528353_1407918/tp78c6b26e/ecoder-ex61094511/add.c')
Building with 'gcc'.
MEX completed successfully.
    mex('add_function.c', '-I/tmp/Bdoc24a_2528353_1407918/tp78c6b26e/ecoder-ex61094511', '/tmp/Bdoc24a_2528353_1407918/tp282a3288_c57d_42e2_9f63_c40ee67fac87/add.o')
Building with 'gcc'.
MEX completed successfully.
### Finish Compiling add_function
### Exit

The output of this script produces:

  • A new model containing the S-function block.

  • A TLC file named add_function.tlc.

  • A C source file named add_function.c.

  • A mexw32 dll file named add_function.mexw32.

4. Add inport blocks and an outport block and make the connections, as shown in the model.

5. Name and save your model. In this example, the model is named ex_function_call_lct.

6. To build the model and generate code, press Ctrl+B.

This code is generated in ex_function_call_lct.c:

/* Exported block signals */
real_T u1;                             /* '<Root>/u1' */
real_T u2;                             /* '<Root>/u2' */

/* External outputs (root outports fed by signals with default storage) */
ExternalOutputs rtY;

/* Model step function */
void ex_function_call_lct_step(void)
{
  /* Outport: '<Root>/y1' incorporates:
   *  Inport: '<Root>/u1'
   *  Inport: '<Root>/u2'
   *  S-Function (add_function): '<Root>/add_function'
   */
  rtY.y1 = add(u1, u2);
}

The user-specified header file add.h is included in ex_function_call_lct.h:

#include "add.h"

Call C Functions by Using a Stateflow Chart

1. Create a C header file named add.h that contains the example function signature. Refer to the preceding example.

2. Create a C source file named add.c that contains the function body. Refer to the preceding example.

3. Add inport blocks and an outport block and make the connections, as shown in the model. In this example, the model is named ex_function_call_SF.

4. Double-click the Stateflow® chart and edit the chart as shown. Place the call to the add function within a transition action.

5. Select the Configuration Parameters > Code Generation > Custom Code pane. On the Code information tab, select Include headers. In the Include headers field, enter the #include statement:

#include "add.h"

6. Select Source files. In the Source files field, enter:

add.c

7. Select the Configuration Parameters > Code Generation > Custom Code > Use the same custom code settings as Simulation Target parameter.

8. To build the model and generate code, press Ctrl+B.

ex_exfunction_call_SF.c contains the following code in the step function:

/* Definition for custom storage class: Global */
real_T u1;                             /* '<Root>/u1' */
real_T u2;                             /* '<Root>/u2' */
real_T y1;                             /* '<Root>/Chart' */

/* Model step function */
void ex_function_call_SF_step(void)
{
  /* Chart: '<Root>/Chart' incorporates:
   *  Inport: '<Root>/u1'
   *  Inport: '<Root>/u2'
   */
  y1 = (real_T)add(u1, u2);
}

ex_exfunction_call_SF.h contains the include statement for add.h:

#include "add.h"

Use MATLAB Function Block to Call C Functions

1. Create a C header file named add.h that contains the example function signature. Refer to the preceding example.

2. Create a C source file named add.c that contains the function body. Refer to the preceding example.

3. In the Simulink Library Browser, click Simulink > User Defined Functions. Drag a MATLAB Function block into your model.

4. Double-click the MATLAB Function block. Edit the function to include:

function y1 = add_function(u1, u2)

% Set the class and size of output
y1 = u1; 

% Call external C function
y1 = coder.ceval('add',u1,u2);

end

5. Select the Configuration Parameters > Code Generation > Custom Code pane. On the Code information tab, select Include headers. In the Include headers field, enter the #include statement:

#include "add.h"

6. In the Code information tab, select Source files. In the Source files field, enter:

add.c

7. Add two Inport blocks and one Outport block to the model and connect it to the MATLAB Function block.

8. Save the model as ex_function_call_ML.

9. To build the model and generate code, press Ctrl+B.

ex_exfunction_call_ML.c contains the following code in the step function:

/* Definition for custom storage class: Global */
real_T u1;                             /* '<Root>/u1' */
real_T u2;                             /* '<Root>/u2' */
real_T y1;                             /* '<Root>/MATLAB Function' */

/* Model step function */
void ex_function_call_ML_step(void)
{
  /* MATLAB Function: '<Root>/MATLAB Function' incorporates:
   *  Inport: '<Root>/u1'
   *  Inport: '<Root>/u2'
   */
  y1 = add(u1, u2);
}

ex_exfunction_call_ML.h contains the include statement for add.h:

#include "add.h"

Related Topics