Writing S-Functions | ![]() ![]() |
Data View
S-function blocks have input and output signals, parameters, and internal states, plus other general work areas. In general, block inputs and outputs are written to, and read from, a block I/O vector. Inputs can also come from
Block outputs can also go to the external outputs via the root outport blocks. In addition to input and output signals, S-functions can have:
You can parameterize S-function blocks by passing parameters to them using the S-function block dialog box.
The following figure shows the general mapping between these various types of data.
An S-function's mdlInitializeSizes routine sets the sizes of the various signals and vectors. S-function methods called during the simulation loop can determine the sizes and values of the signals.
An S-function method can access input signals in two ways:
Accessing Signals Using Pointers
During the simulation loop, accessing the input signals is performed using
This is an array of pointers, where portIndex
starts at 0. There is one for each input port. To access an element of this signal you must use
Note that input array pointers can point at noncontiguous places in memory. You can retrieve the output signal by using this code.
Accessing Contiguous Input Signals
An S-function's mdlInitializeSizes
method can specify that the elements of its input signals must occupy contiguous areas of memory, using ssSetInputPortRequiredContiguous. If the inputs are contiguous, other methods can use ssGetInputPortSignal to access the inputs.
Accessing Input Signals of Individual Ports
This section describes how to access all input signals of a particular port and write them to the output port. The preceding figure shows that the input array of pointers can point to noncontiguous entries in the block I/O vector. The output signals of a particular port form a contiguous vector. Therefore, the correct way to access input elements and write them to the output elements (assuming the input and output ports have equal widths) is to use this code.
int_T element; int_T portWidth = ssGetInputPortWidth(S,inputPortIndex); InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,inputPortIndex); real_T *y = ssGetOutputPortSignal(S,outputPortIdx); for (element=0; element<portWidth; element++) { y[element] = *uPtrs[element]; }
A common mistake is to try to access the input signals via pointer arithmetic. For example, if you were to place
just below the initialization of uPtrs
and replace the inner part of the above loop with
the code compiles, but the MEX-file might crash Simulink. This is because it is possible to access invalid memory (which depends on how you build your model). When accessing the input signals incorrectly, a crash occurs when the signals entering your S-function block are not contiguous. Noncontiguous signal data occurs when signals pass through virtual connection blocks such as the Mux or Selector blocks.
To verify that you are correctly accessing wide input signals, pass a replicated signal to each input port of your S-function. You do this by creating a Mux block with the number of input ports equal to the width of the desired signal entering your S-function. Then the driving source should be connected to each input port as shown in this figure.
![]() | Process View | Writing Callback Methods | ![]() |