MATLAB: S-Function PWork pointers and memory allocation error
cs-functionsimulink
Related Solutions
First, the S-Function needs to specify how many PWork vectors it needs (using ssSetNumPWork) either in mdlInitializeSizes or in mdlSetWorkWidths. Simulink calls the above functions in the S-Function at the beginning of the model initialization stage (internally we refer to this part of the initialization stage as the compile phase). Towards the end of model initialization stage (internally we refer to this part of the initialization stage as the link phase), Simulink allocates the specified number of PWorks. Upon completing the model initialization stage, Simulink calls the S-Function's mdlStart. In the mdlStart function, the S-Function can allocate memory and store a pointer to it in the PWork array. The following code snippet illustrates specifying, allocating, using, and freeing memory using PWorks.
mdlInitializeSizes(SimStruct* S) { /* snip */ssSetNumPWork(S, 1);/* snip */ }mdlStart(SimStruct* S) { /* snip */void* ptr = malloc(1024 /* number of bytes */); if (ptr == NULL) { /* report memory allocation error */ ssSetErrorStatus(S, "Memory allocation error"); return; } ssSetPWorkValue(S, 0, ptr);/* snip */ }mdlOutputs(SimStruct* S, int_T tid) { void* ptr = ssGetPWorkValue(S, 0);/* snip */ }mdlTerminate(SimStruct* S) { /* snip *//* free the memory allocated in mdlStart */ if (ssGetPWork(S) != NULL) { void* ptr = ssGetPWorkVale(S,0); if (ptr != NULL) free(ptr); }/* snip */ }
For a more complete example on using PWork vectors please look at the following example in the documentation.
You cannot access a single instance of your C++ object between different S-Functions but you can share access to a single object between multiple instances of a single S-function. Attached is a modified version of the C++ 'Counter' S-Function demo (sfncdemo_counter_cpp.mdl) that uses the STATIC keyword to create a single instance of the counter class that is accessed by both instances of the S-Function.
In the original file the Start and Output functions are written as follows:
#define MDL_START /* Change to #undef to remove function */ #if defined(MDL_START) /* Function: mdlStart ======================================================= * Abstract: * This function is called once at start of model execution. If you * have states that should be initialized once, this is the place * to do it. */ static void mdlStart(SimStruct *S) { ssGetPWork(S)[0] = (void *) new counter; // store new C++ object in the } // pointers vector #endif /* MDL_START */ /* Function: mdlOutputs =======================================================* Abstract:* In this function, you compute the outputs of your S-function* block.*/ static void mdlOutputs(SimStruct *S, int_T tid) { counter *c = (counter *) ssGetPWork(S)[0]; real_T *y = ssGetOutputPortRealSignal(S,0); // the pointers vector and use y[0] = c->output(); // member functions of the UNUSED_ARG(tid); // object }
The modified version replaces the line
counter *c = (counter *) ssGetPWork(S)[0];
with
static counter *c = (counter *) ssGetPWork(S)[0];
The "static" keyword prevents the creation of a second counter by the second instance of the S-Function block.
Best Answer