I have been developing a block in Scilab/Xcos (open source variant of Matlab/Simulink) with C language usage. For that purpose the Scilab/Xcos offers a special block called CBLOCK4. As soon as I place this block into the simulation a C language stub is automatically generated. Part of that stub is a template for a function which implements the behavior of the block. This function accepts among its parameters pointer to a scicos_block structure:
typedef struct {
int nevprt;
voidg funpt ;
int type;
int scsptr;
int nz;
double *z;
int noz;
int *ozsz;
int *oztyp;
void **ozptr;
int nx;
double *x;
double *xd;
double *res;
int nin;
int *insz;
void **inptr;
int nout;
int *outsz;
void **outptr;
int nevout;
double *evout;
int nrpar;
double *rpar;
int nipar;
int *ipar;
int nopar;
int *oparsz;
int *opartyp;
void **oparptr;
int ng;
double *g;
int ztyp;
int *jroot;
char *label;
void **work;
int nmode;
int *mode;
} scicos_block;
The item work is probably intended to be used for storage of the address at which another address is stored at which the internal state variables of the block are stored. I have attempted to implement the Scilab/Xcos block with the work item usage:
#include "scicos_block4.h"
#define U ((double *)GetRealInPortPtrs(block, 1))
#define Y ((double *)GetRealOutPortPtrs(block, 1))
// parameters
#define Tu (GetRparPtrs(block)[0])
#define Td (GetRparPtrs(block)[1])
#define T (GetRparPtrs(block)[2])
void Ramp(scicos_block *block, int flag)
{
double *target;
double *inputDelta;
double *out;
if(flag == 4)
{
/* init */
if((*(block->work) = (double *)scicos_malloc(sizeof(double)*3)) == NULL)
{
set_block_error(-16);
return;
}
target = (double*)(*(block->work));
inputDelta = (double*)(*(block->work + 1));
out = (double*)(*(block->work + 2));
*target = 0;
*inputDelta = 0;
*out = 0;
}
else if(flag == 1)
{
/* output computation */
if(U[0] != *target)
{
*target = U[0];
if(*target - Y[0] < 0)
{
*inputDelta = Y[0] - *target;
}
else
{
*inputDelta = *target - Y[0];
}
}
if(*target > Y[0])
{
*out += *inputDelta*T/Tu;
if(*out > *target)
{
*out = *target;
}
}
else if(*target < Y[0])
{
*out -= *inputDelta*T/Td;
if(*out < *target)
{
*out = *target;
}
}
Y[0] = *out;
}
else if (flag == 5)
{
/* ending */
scicos_free(*(block->work));
}
}
I am able to successfully compile the block containing this code but in case I start the simulation it crashes. I have doubts regarding the dynamic allocation of the memory and the way how I work with it.
Please could anybody take a look at my code (namely the part in the body of the if with flag == 4) and tell me what I am doing wrong?
This line
is correct but these lines
are wrong.
(*(block->work)will give you the pointer to the first of the three malloc'ed doubles.However, you don't get the next double like you did - you are adding one too early. Change it like:
Or simply do it like:
BTW: You don't need all the casting. Just remove it.
Edit: In a comment OP tells that it still crashes
The posted code doesn't tell us whether
block->workhas been initialized before callingRamp. If it hasn't been initialized before then doing*(block->work)will be illegal - and may cause a crash.So maybe the code is missing something like: