C++ s-function with dynamically sized output, not dependent on input size
14 views (last 30 days)
Show older comments
I am trying to create a C++ s-function that has an output of a variable sized vector. I have found some examples that have a variable sized output, where the output is dependent on the input, such as sfcndemo_varsize from:
However, my function does not set the size based on the inputs. In the mdlOutputs() function, I call a c++ function from another file which outputs a vector, and then get the size of that vector.
static void mdlOutputs(SimStruct *S, int_T tid) {
// Call the function
// result is a structure that includes vector 'headings'
result = update();
const std::vector headings = result.headings;
int_T headingSize = static_cast<int_T>(headings.size());
if (headingSize > 0) {
for (size_t i = 0; i < headings.size(); i++) {
y2[i] = static_cast<real_T>(headings[i]); // Store each heading
}
}
else {
y2[0] = 0.0; // Default if no heading data
}
}
Is it possible to set the s-function output size from mdlOutputs? This code does not appear to ever trigger the mdlSetOutputPortDimensionInfo() which I have also defined.
2 Comments
Amish
on 25 Mar 2025
The following answer on the community might be helpful: https://www.mathworks.com/matlabcentral/answers/401792-how-can-i-write-a-level-2-matlab-s-function-where-the-input-and-output-might-have-unknown-dimensions
Answers (2)
Harsh
on 26 Mar 2025
You cannot change the output port dimensions from the “mdlOutputs” function. In Simulink, any changes to signal dimensions must be performed during the dimension propagation phase and not during runtime execution in “mdlOutputs”. To have a dynamically sized output, you need to declare the port as “DYNAMICALLY_SIZED” in “mdlInitializeSizes”.
By default, the Simulink engine calls “mdlSetOutputPortDimensionInfo” only if it can fully determine the dimensionality of port from the port to which it is connected. If the engine cannot completely determine the dimensionality from port connectivity, it invokes “mdlSetDefaultPortDimensionInfo”. Therefore, you can set the output port dimensions info there by calling the “update” method and then call “update” function again in “mdlOutputs” to set the values also.
Below is the sample code snippet to achieve this task -
- “update” function to return a vector of headings
static std::vector<double> update(int &size) {
size = 3 ;
std::vector<double> headings(size); // Allocate vector of 'size' elements
for (int i = 0; i < size; i++) {
headings[i] = i;
}
return headings;
}
- Set the output port width to “DYNAMICALLY_SIZED” in “”mdlInitializeSizes”
static void mdlInitializeSizes(SimStruct *S) {
ssSetNumSFcnParams(S, 0);
if (!ssSetNumInputPorts(S, 0)) return;
if (!ssSetNumOutputPorts(S, 1)) return;
ssSetOutputPortWidth(S, 0, DYNAMICALLY_SIZED);
ssSetNumSampleTimes(S, 1);
ssSetOptions(S, 0);
}
- Set the output port dimensions to [1xn] where n is the size of headings vector in the "mdlSetDefaultPortDimensionInfo"
// mdlSetDefaultPortDimensionInfo: Set default port size based on update() output.
#define MDL_SET_DEFAULT_PORT_DIMENSION_INFO
void mdlSetDefaultPortDimensionInfo(SimStruct *S) {
int headingSize = 0;
std::vector<double> headings = update(headingSize);
if (ssGetOutputPortWidth(S, 0) == DYNAMICALLY_SIZED) {
ssSetOutputPortMatrixDimensions(S, 0, 1, headingSize);
}
}
- set the output port value in the "mdlOutputs" function
static void mdlOutputs(SimStruct *S, int_T tid) {
int headingSize = 0;
std::vector<double> headings = update(headingSize);
real_T *y = ssGetOutputPortRealSignal(S, 0);
if (!headings.empty()) {
for (int i = 0; i < headingSize; i++) {
y[i] = headings[i];
}
} else {
y[0] = 0.0;
}
}
- Below is the snapshot of Simulink model and the output visualized via a “scope” block


1 Comment
Aryan
on 8 Aug 2025
Edited: Aryan
on 8 Aug 2025
Hi,
I understand you want to create a C++ S-Function (CPP FILE) in SIMULINK where the output vector size can change at each simulation step, based on the result of a function call in "mdlOutputs".
Even if we set the output port as "DYNAMICALLY_SIZED" and implement "mdlSetOutputPortDimensionInfo", SIMULINK doesn’t actually update the output size during simulation.
It’s because SIMULINK only negotiates signal dimensions during model compilation and dimension propagation—never at runtime. Once the simulation starts, the output port size is fixed.
Workaround is to define the output port with the maximum possible size you expect, and then provide a second output that tells you how many elements are valid at each time step. The unused elements in the output vector can be set to zero (or NaN, if you prefer). This approach works reliably with SIMULINK.
Here’s a basic example of how you might set this up in your S-Function (CPP FILE):
#define S_FUNCTION_NAME sample
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
#include <cstdlib> // for rand(), srand()
#include <ctime> // for time()
#define MAX_HEADINGS 10
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 0);
// No input ports
if (!ssSetNumInputPorts(S, 0)) return;
// Two outputs: vector and count
if (!ssSetNumOutputPorts(S, 2)) return;
ssSetOutputPortWidth(S, 0, MAX_HEADINGS); // Headings vector (fixed size)
ssSetOutputPortDataType(S, 0, SS_DOUBLE);
ssSetOutputPortWidth(S, 1, 1); // Valid count (scalar)
ssSetOutputPortDataType(S, 1, SS_INT32);
ssSetNumSampleTimes(S, 1);
ssSetOptions(S, 0);
}
// Optional: Seed the RNG once at start
static void mdlStart(SimStruct *S)
{
srand(static_cast<unsigned int>(time(0)));
}
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, 1.0);
ssSetOffsetTime(S, 0, 0.0);
}
static void mdlOutputs(SimStruct *S, int_T tid)
{
// Generate n in [1, MAX_HEADINGS]
int_T n = (rand() % MAX_HEADINGS) + 1;
// Output port pointers
real_T *y_headings = ssGetOutputPortRealSignal(S, 0);
int_T *y_count = (int_T*)ssGetOutputPortSignal(S, 1);
// Fill output vector with 1, 2, ..., n
int_T i = 0;
for (; i < n; ++i) {
y_headings[i] = static_cast<real_T>(i + 1);
}
// Fill remaining with zeros
for (; i < MAX_HEADINGS; ++i) {
y_headings[i] = 0.0;
}
// Output the valid count
y_count[0] = n;
}
static void mdlTerminate(SimStruct *S) { }
#ifdef MATLAB_MEX_FILE
#include "simulink.c"
#else
#include "cg_sfun.h"
#endif
Below are some snapshots of how simulation will look like:


Kindly refer to the following MathWorks documentation links for better understanding the functions used above:
Hope it helps !
0 Comments
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!