Write Wrapper S-Function and TLC Files
Create S-functions that work seamlessly with the Simulink® and code generator products by using the wrapper concept. You can:
- Interface your algorithms in Simulink models by writing MEX S-function wrappers ( - sfunction.mex
- Direct the code generator to insert your algorithm into the generated code by creating a TLC S-function wrapper ( - sfunction.tlc
MEX S-Function Wrapper
Creating S-functions by using an S-function wrapper enables you to insert C/C++ code algorithms in Simulink models and the generated code with little or no change to your original C/C++ function. A MEX S-function wrapper is an S-function that calls code, which resides in another module.
Note
Use a MEX S-function wrapper only in the MATLAB® version in which you created the wrapper.
Suppose that you have an algorithm (that is, a C function) called
                    my_alg that resides in the file my_alg.c.
                You can integrate my_alg into a Simulink model by creating a MEX S-function wrapper (for example,
                    wrapsfcn.c). A Simulink model can then call my_alg from an S-Function
                block. The Simulink S-function contains a set of empty functions that the Simulink engine requires for various API related purposes. For example,
                although only mdlOutputs calls my_alg, the
                engine calls mdlTerminate, even though this S-function routine
                performs no action.
You can embed the call to my_alg in the generated code by
                creating a TLC S-function wrapper (for example, wrapsfcn.tlc).
                You can eliminate the empty function calls. You can avoid the overhead of executing
                the mdlOutputs function and you can then eliminate the
                    my_alg function.
Wrapper S-functions are useful when you are creating algorithms that are procedural or when you are integrating legacy code into a Simulink model. If you want to create code that is:
- Interpretive in nature (that is, highly parameterized by operating modes) 
- Heavily optimized (that is, no extra tests to decide what mode the code is operating in) 
then you must create a fully inlined TLC file for your S-function.
The next figure shows the wrapper S-function concept.

Using an S-function wrapper to import algorithms into your Simulink model means that the S-function serves as an interface that calls your
                C/C++ algorithms from mdlOutputs. You can quickly integrate
                large standalone C/C++ programs into your model without having to change the
                code.
This sample model includes an S-function wrapper.

Two files are associated with the wrapsfcn block: the
                S-function wrapper and the C/C++ code that contains the algorithm. The first three
                statements:
- Define the name of the S-function (what you enter in the Simulink S-Function block dialog box). 
- Specify that the S-function is using the level 2 format. 
- Provide access to the - SimStructdata structure.- SimStructcontains pointers to data used during simulation and code generation and defines macros that store data in and retrieve data from the- SimStruct.
#define S_FUNCTION_NAME wrapsfcn
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
extern real_T my_alg(real_T u);  /* Declare my_alg as extern */
/*
 * mdlInitializeSizes - initialize the sizes array
 */
static void mdlInitializeSizes(SimStruct *S)
{
    ssSetNumSFcnParams( S, 0); /*number of input arguments*/
    if (!ssSetNumInputPorts(S, 1)) return;
    ssSetInputPortWidth(S, 0, 1);
    ssSetInputPortDirectFeedThrough(S, 0, 1);
    if (!ssSetNumOutputPorts(S,1)) return;
    ssSetOutputPortWidth(S, 0, 1);
    
    ssSetNumSampleTimes( S, 1);
}
/*
 * mdlInitializeSampleTimes - indicate that this S-function runs
 * at the rate of the source (driving block)
 */
static void mdlInitializeSampleTimes(SimStruct *S)
{
    ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
    ssSetOffsetTime(S, 0, 0.0);
} 
/*
 * mdlOutputs - compute the outputs by calling my_alg, which
 * resides in another module, my_alg.c
 */
static void mdlOutputs(SimStruct *S, int_T tid)
{
    InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
    real_T            *y    = ssGetOutputPortRealSignal(S,0);
    *y = my_alg(*uPtrs[0]); /* Call my_alg in mdlOutputs */
 }
/*
 * mdlTerminate - called when the simulation is terminated.
 */
static void mdlTerminate(SimStruct *S)
{
}
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endifFor more information, see Templates for C S-Functions.
The S-function routine mdlOutputs contains a function call to
                    my_alg, which is the C function containing the algorithm
                that the S-function performs. For my_alg.c, the code is:
#ifdef MATLAB_MEX_FILE
#include "tmwtypes.h"
#else
#include "rtwtypes.h"
#endif
real_T my_alg(real_T u)
{
return(u * 2.0);
}For more information, see Manage Build Process File Dependencies.
The wrapper S-function wrapsfcn calls
                    my_alg, which computes u * 2.0. To build
                    wrapsfcn.mex, use this command:
mex wrapsfcn.c my_alg.c
TLC S-Function Wrapper
A TLC S-function wrapper is a TLC file that specifies how the code generator calls
                your code. For example, you can inline the call to my_alg in
                the mdlOutputs section of the generated code. In the MEX S-Function Wrapper example, the call to my_alg
                is embedded in the mdlOutputs section as:
*y = my_alg(*uPtrs[0]);
When you are creating a TLC S-function wrapper, the goal is to embed the same type of call in the generated code.
Look at how the code generator executes S-functions that are not inlined. A
                noninlined S-function is identified by the absence of the file
                        sfunction.tlcsfunction.mexmdlOutputs through a function pointer that, in this
                example, then calls my_alg.
The wrapper example contains one S-function, wrapsfcn.mex. You
                must compile and link an additional module, my_alg, with the
                generated code. At the MATLAB command prompt, enter:
set_param('wrapper/S-Function','SFunctionModules','my_alg')
Code Overhead for Noninlined S-Functions
The code generated when using grt.tlc as the system target file
                    without
                wrapsfcn.tlc is:
<Generated code comments for wrapper model with noninlined wrapsfcn S-function>
#include <math.h>
#include <string.h>
#include "wrapper.h"
#include "wrapper.prm"
/* Start the model */
void mdlStart(void)
{
  /* (start code not required) */
}
/* Compute block outputs */
void mdlOutputs(int_T tid)
{
  /* Sin Block: <Root>/Sin */
  rtB.Sin = rtP.Sin.Amplitude *
    sin(rtP.Sin.Frequency * ssGetT(rtS) + rtP.Sin.Phase);
  /* Level2 S-Function Block: <Root>/S-Function (wrapsfcn) */
  {
    /* Noninlined S-functions create a SimStruct object and
     * generate a call to S-function routine mdlOutputs
     */
    SimStruct *rts = ssGetSFunction(rtS, 0);
    sfcnOutputs(rts, tid);
  }
  /* Outport Block: <Root>/Out */
  rtY.Out = rtB.S_Function;
}
/* Perform model update */
void mdlUpdate(int_T tid)
{
  /* (update code not required) */
}
/* Terminate function */
void mdlTerminate(void)
{
  /* Level2 S-Function Block: <Root>/S-Function (wrapsfcn) */
  {
/* Noninlined S-functions require a SimStruct object and
     * the call to S-function routine mdlTerminate
     */
    SimStruct *rts = ssGetSFunction(rtS, 0);
    sfcnTerminate(rts);
  }
}
#include "wrapper.reg"
/* [EOF] wrapper.c */The wrapper.reg generated file contains the initialization of
                the SimStruct for the wrapper S-Function block. There is one
                child SimStruct for each S-Function block in your model. You can
                significantly reduce this overhead by creating a TLC wrapper for the
                S-function.
Inline a Wrapper S-Function
The generated code makes the call to your S-function,
                    wrapsfcn.c, in mdlOutputs by using this
                code:
SimStruct *rts = ssGetSFunction(rtS, 0); sfcnOutputs(rts, tid);
This call has computational overhead associated with it. The Simulink engine creates a SimStruct data structure for the
                S-Function block. The code generator constructs a call through a function pointer to
                execute mdlOutputs, then mdlOutputs calls
                    my_alg. By inlining the call to your C/C++ algorithm,
                    my_alg, you can eliminate both the
                    SimStruct and the extra function call, thereby improving the
                efficiency and reducing the size of the generated code.
Inlining a wrapper S-function requires an
                        sfunction.tlcmy_alg. The figure shows the relationships between the
                algorithm, the wrapper S-function, and the
                        sfunction.tlc

To inline the call to my_alg, place your function call in an
                        sfunction.tlcwrapsfcn.tlc). The
                Target Language Compiler overrides the default method of placing calls to your
                S-function in the generated code. 
This code is the TLC file wrapsfcn.tlc that inlines
                    wrapsfcn.c:
%% File : wrapsfcn.tlc %% Abstract: %% Example inlined tlc file for S-function wrapsfcn.c %% %implements "wrapsfcn" "C" %% Function: BlockTypeSetup ==================================================== %% Abstract: %% Create function prototype in model.h as: %% "extern real_T my_alg(real_T u);" %% %function BlockTypeSetup(block, system) void %openfile buffer extern real_T my_alg(real_T u); /* This line is placed in wrapper.h */ %closefile buffer %<LibCacheFunctionPrototype(buffer)> %endfunction %% BlockTypeSetup %% Function: Outputs =========================================================== %% Abstract: %% y = my_alg( u ); %% %function Outputs(block, system) Output /* %<Type> Block: %<Name> */ %assign u = LibBlockInputSignal(0, "", "", 0) %assign y = LibBlockOutputSignal(0, "", "", 0) %% PROVIDE THE CALLING STATEMENT FOR "algorithm" %% The following line is expanded and placed in mdlOutputs within wrapper.c %<y> = my_alg(%<u>); %endfunction %% Outputs
The first section of this code inlines the wrapsfcn S-Function
                block and generates the code in C:
%implements "wrapsfcn" "C"
The next task is to inform the code generator that the routine
                    my_alg must be declared as external in the generated
                    wrapper.h file for any
                wrapsfcn S-Function blocks in the model. Do this declaration once
                for all
                wrapsfcn S-Function blocks by using the
                    BlockTypeSetup function. In this function, you direct the
                Target Language Compiler to create a buffer and cache the my_alg
                as extern in the wrapper.h generated header
                file.
The final step is the inlining of the call to the function
                    my_alg. The Outputs function inlines
                the call. In this function, you access the block input and output and place a direct
                call to my_alg. The call is embedded in
                    wrapper.c.
The Inlined Code
The code generated when you inline your wrapper S-function is similar to the
                default generated code. The mdlTerminate function does not
                contain a call to an empty function and the mdlOutputs function
                now directly calls my_alg.
void mdlOutputs(int_T tid)
{
  /* Sin Block: <Root>/Sin */
  rtB.Sin = rtP.Sin.Amplitude *
    sin(rtP.Sin.Frequency * ssGetT(rtS) + rtP.Sin.Phase);
  /* S-Function Block: <Root>/S-Function */
  rtB.S_Function = my_alg(rtB.Sin); /* Inlined call to my_alg */
  /* Outport Block: <Root>/Out */
  rtY.Out = rtB.S_Function;
}wrapper.reg does not create a child
                    SimStruct for the S-function because the generated code is
                calling my_alg directly, eliminating over 1 KB of memory
                usage.