PWork loses data in S-function

4 ビュー (過去 30 日間)
Steradiant
Steradiant 2021 年 2 月 18 日
コメント済み: Steradiant 2021 年 3 月 3 日
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?

採用された回答

Mark McBroom
Mark McBroom 2021 年 2 月 20 日
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 件のコメント
Mark McBroom
Mark McBroom 2021 年 2 月 21 日
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 2021 年 3 月 3 日
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.

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeBlock and Blockset Authoring についてさらに検索

製品


リリース

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by