PWork loses data in S-function

5 views (last 30 days)
Steradiant
Steradiant on 18 Feb 2021
Commented: Steradiant on 3 Mar 2021
Hello,
I want to read out the data (which are structures) from the S-functions parameter dialog at Startup and use them in every cycle. Therefore, I wrote the following MWE
#define S_FUNCTION_NAME s_fun_paratest /* Defines and Includes */
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
#define MDL_START
struct myStruct1{
mxDouble data1, data2;
};
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 1); /* Number of expected parameters */
#if defined(MATLAB_MEX_FILE)
if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) {
// mdlCheckParameters(S);
if (ssGetErrorStatus(S) != NULL) {
return;
}
} else {
return; /* Parameter mismatch reported by the Simulink engine*/
}
#endif
ssSetNumPWork(S, 1);
// ssSetSFcnParamTunable(S,0,false);
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, DYNAMICALLY_SIZED);
ssSetInputPortDirectFeedThrough(S, 0, 1);
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, DYNAMICALLY_SIZED);
ssSetNumSampleTimes(S, 1);
/* Take care when specifying exception free code - see sfuntmpl.doc */
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
}
static void mdlStart(SimStruct *S)
{
struct myStruct1 st1, *st2;
mxArray *tmp;
tmp = mxGetField(ssGetSFcnParam(S,0),0,"maxIter");
if (tmp == NULL)
mexErrMsgIdAndTxt("MATLAB:SIMULINK","maxIter not existing.");
st1.data1 = *mxGetDoubles(tmp);
ssGetPWork(S)[0] = &st1;
mexPrintf("\nst1.data1: %f", st1.data1); // <- outputs the correct value
st2 = ssGetPWork(S)[0];
mexPrintf("\nst2.data1: %f", st2->data1); // <- outputs the correct value
}
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
}
static void mdlOutputs(SimStruct *S, int_T tid)
{
struct myStruct1 *st2;
st2 = ssGetPWork(S)[0];
mexPrintf("\nst2.data1: %f", st2->data1); // <- outputs 0
}
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 */
endif
I marked the problem in the mdlOutputs . I've already checked the addresses of ssGetPWork(S) and ssGetPWork(S)[0] and they are the same in mdlStart and mdlOutputs. Do you have any ideas what i'm missing?

Accepted Answer

Mark McBroom
Mark McBroom on 20 Feb 2021
st1 is an autmomatic variable, so its memory location can get reused after leaving mdlStart(). YOu need to allocation memory for st1 in mdlStart and save this malloc'd address in PWork.
  3 Comments
Mark McBroom
Mark McBroom on 21 Feb 2021
You should initialize the memory in mdlStart() because this gets called at the beginning of a simulation. mdlInitializeSizes gets called at the start of simulation, but also gets called when updating the simulation model. You don't want to allocate the memory if the model is only being updated and not simulated.
If you were able share data via the stack it was just lucky that it worked. Stack data can be reused by the operating system for other purposes when returning from the function.
Steradiant
Steradiant on 3 Mar 2021
I see. Thanks for the information. Regarding the pointers, the difference is, that I have a main function, the mexFunction in the MEX C-Code from where I call the subprograms. In these function calls I use pointers created in the mexFunction. For S-functions on the other hand, there is obviously nothing like a main function. Depending on the current stage of the simulink Simulation, a different routine is carried out.

Sign in to comment.

More Answers (0)

Categories

Find more on Block and Blockset Authoring in Help Center and File Exchange

Products


Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!