The C structure of a Scicos block defines all the fields to handle data provided by the simulator such inputs/outputs, parameters, states, ...
That structure of type scicos_block is defined in the file scicos_block4.h, and user must include that header in each computational functions in the form :
#include "scicos_block4.h" void mycomputfunc(scicos_block *block,int flag) { ... }
The fields, that can be either C pointers or directly data, are then accessible via the *block structure :
block->field
This access is a direct approach and most of users should prefer the C_macros approach for facilities purpose.
In the current version of Scicos, the scicos->block structure is defined :
/* scicos_block structure definition */ 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;
model.in = [3;1;4]
model.in2 = [2;1;1]
model.intyp = [2;1;3]
and the corresponding block->insz field at C computational function level will be coded as :
Do the difference here in the type numbers defined at the Scilab level (2,1,3) and the type numbers defined at the C level (84,11,10). The following table gives the correspondance for all Scicos type:
Scilab Type | Scilab Number | C Type | C Number |
real | 1 | double | 10 |
complex | 2 | double | 11 |
int32 | 3 | long | 84 |
int16 | 4 | short | 82 |
int8 | 5 | char | 81 |
uint32 | 6 | unsigned long | 814 |
uint16 | 7 | unsigned short | 812 |
uint8 | 8 | unsigned char | 811 |
For i.e., to directly access to the data, the user can use theses instructions :
#include "scicos_block4.h"
...
SCSINT32_COP *ptr_i;
SCSCOMPLEX_COP *ptr_dc;
SCSREAL_COP *ptr_d;
int n1,m1;
SCSINT32_COP cumsum_i=0;
int i;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get the ptrs of the first int32 regular input port*/
ptr_i = (SCSINT32_COP *) block->inptr[0];
/*get the ptrs of the second complex regular input port*/
ptr_dc = (SCSCOMPLEX_COP *) block->inptr[1];
/*get the ptrs of the third real regular input port*/
ptr_d = (SCSREAL_COP *) block->inptr[2];
...
/*get the dimension of the first int32 regular input port*/
n1=block->insz[0];
m1=block->insz[3];
...
/*compute the cumsum of the input int32 matrix*/
for(i=0;i<n1*m1;i++) {
cumsum_i += ptr_i[i];
}
...
}
One can also use the set of C macros :
GetInPortPtrs(blk,x), GetRealInPortPtrs(block,x),
GetImagInPortPtrs(block,x), Getint8InPortPtrs(block,x),
Getint16InPortPtrs(block,x), Getint32InPortPtrs(block,x),
Getuint8InPortPtrs(block,x), Getuint16InPortPtrs(block,x),
Getuint32InPortPtrs(block,x)
to have the appropiate pointer of the data to handle and
GetNin(block), GetInPortRows(block,x),
GetInPortCols(block,x), GetInPortSize(block,x,y),
GetInType(block,x), GetSizeOfIn(block,x)
to handle number, dimensions and type of regular input ports.
(x is numbered from 1 to nin and y numbered from 1 to 2).
For the previous example that gives :
#include "scicos_block4.h"
...
SCSINT32_COP *ptr_i;
SCSCOMPLEX_COP *ptr_dc;
SCSREAL_COP *ptr_d;
int n1,m1;
SCSINT32_COP cumsum_i=0;
int i;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get the ptrs of the first int32 regular input port*/
ptr_i = Getint32InPortPtrs(block,1);
/*get the ptrs of the second complex regular input port*/
ptr_dc = GetRealInPortPtrs(block,2);
/*get the ptrs of the third real regular input port*/
ptr_d = GetRealInPortPtrs(block,3);
...
/*get the dimension of the first int32 regular input port*/
n1=GetInPortRows(block,1);
m1=GetInPortCols(block,1);
...
}
Finally note that the regular input port registers are only accessible for reading.
model.out = [3;1;4]
model.out2 = [2;1;1]
model.outtyp = [2;1;3]
and the corresponding block->outsz field at C computational function level will be coded as :
Do the difference here in the type numbers defined at the Scilab level (2,1,3) and the type numbers defined at the C level (84,11,10) and please report to the previous table to have the correspondence for all Scicos type.
For i.e., to directly access to the data, the user can use theses instructions :
#include "scicos_block4.h"
...
SCSINT32_COP *ptr_i;
SCSCOMPLEX_COP *ptr_dc;
SCSREAL_COP *ptr_d;
int n1,m1;
SCSINT32_COP cumsum_i=0;
int i;
...
void mycomputfunc(scicos_block *block,int flag)
{
/*get the ptrs of the first int32 regular output port*/
ptr_i = (SCSINT32_COP *) block->outptr[0];
/*get the ptrs of the second complex regular output port*/
ptr_dc = (SCSCOMPLEX_COP *) block->outptr[1];
/*get the ptrs of the third real regular output port*/
ptr_d = (SCSREAL_COP *) block->outptr[2];
...
/*get the dimension of the first int32 regular output port*/
n1=block->outsz[0];
m1=block->outsz[3];
...
/*compute the cumsum of the output int32 matrix*/
for(i=0;i<n1*m1;i++) {
cumsum_i += ptr_i[i];
}
...
}
One can also use the set of C macros :
GetOutPortPtrs(block,x), GetRealOutPortPtrs(block,x),
GetImagOutPortPtrs(block,x), Getint8OutPortPtrs(block,x),
Getint16OutPortPtrs(block,x), Getint32OutPortPtrs(block,x),
Getuint8OutPortPtrs(block,x), Getuint16OutPortPtrs(block,x),
Getuint32OutPortPtrs(block,x)
to have the appropiate pointer of the data to handle and
GetNout(block), GetOutPortRows(block,x),
GetOutPortCols(block,x), GetOutPortSize(block,x,y),
GetOutType(block,x), GetSizeOfOut(block,x)
to handle number, dimensions and type of regular output ports.
(x is numbered from 1 to nout and y is numbered from 1 to 2).
For the previous example that gives :
#include "scicos_block4.h"
...
SCSINT32_COP *ptr_i;
SCSCOMPLEX_COP *ptr_dc;
SCSREAL_COP *ptr_d;
int n1,m1;
SCSINT32_COP cumsum_i=0;
int i;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get the ptrs of the first int32 regular output port*/
ptr_i = GetOutPortPtrs(block,1);
/*get the ptrs of the second complex regular output port*/
ptr_dc = GetRealOutPortPtrs(block,2);
/*get the ptrs of the third real regular output port*/
ptr_d = GetRealOutPortPtrs(block,3);
...
/*get the dimension of the first int32 regular output port*/
n1=GetOutPortRows(block,1);
m1=GetOutPortCols(block,1);
...
}
Finally note that the regular output port registers must be only written for flag=1.
For i.e, suppose that you want generate an event with the first event output port, 1ms after each calls of the block, then you'll use :
#include "scicos_block4.h"
...
void mycomputfunc(scicos_block *block,int flag)
{
...
if (flag==3) {
block->evout[0]=0.001;
}
...
}
Note that every events generated from output event register will be asynchronous with event
coming from event input port (even if you set block->evout[x]=0).
The event output register must be only written for flag=3.
model.rpar = [%pi;%pi/2;%pi/4]
you can retrieve the previous data in the C computational function with :
#include "scicos_block4.h"
...
double PI;
double PI_2;
double PI_4;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get the first value of the real param register*/
PI = block->rpar[0];
/*get the second value of the real param register*/
PI_2 = block->rpar[1];
/*get the third value of the real param register*/
PI_4 = block->rpar[2];
...
}
You can also use the C macro GetRparPtrs(block) to get the pointer of the real parameter register. For i.e., if we define the following scicos_model in an interfacing function of a scicos block :
A = [1.3 ; 4.5 ; 7.9 ; 9.8];
B = [0.1 ; 0.98];
model.rpar = [A;B]
in the corresponding C computational function of that block, we'll use :
#include "scicos_block4.h"
...
double *rpar;
double *A;
double *B;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get ptrs of the real param register*/
rpar = GetRparPtrs(block);
/*get the A ptrs array*/
A = rpar;
/*get the B ptrs array*/
B = &rpar[4];
/*or B = rpar + 4;*/
...
}
Note that real parameters register is only accessible for reading.
model.ipar = [(1:3)';5]
you can retrieve the previous data in the C computational function with :
#include "scicos_block4.h"
...
int one;
int two;
int three;
int five;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get the first value of the integer param register*/
one = block->ipar[0];
/*get the second value of the integer param register*/
two = block->ipar[1];
/*get the third value of the integer param register*/
three = block->ipar[2];
/*get the fourth value of the integer param register*/
five = block->ipar[3];
...
}
You can also use the C macro GetIparPtrs(block) to get the pointer of the
real parameter register.
Most of time in the scicos C block libraries, the integer register is used to
parametrize the length of real parameters. For i.e. if you define the following
scicos_model
in a block :
// set a random size for the first real parameters
A_sz = int(rand(10)*10);
// set a random size for the second real parameters
B_sz = int(rand(10)*10);
// set the first real parameters
A = rand(A_sz,1,``uniform'');
// set the second real parameters
B = rand(B_sz,1,``normal'');
// set ipar
model.ipar = [A_sz;B_sz]
// set rpar (length of A_sz+B_sz)
model.rpar = [A;B]
the array of real parameters (parametrized by ipar) can be retrieved in the correspondig C computational function with :
#include "scicos_block4.h"
...
int A_sz;
int B_sz;
double *rpar;
double *A;
double *B;
double cumsum;
int i;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get ptrs of the real param register*/
rpar = GetRparPtrs(block);
/*get size of the first real param register*/
A_sz = block->ipar[0];
/*get size of the second real param register*/
B_sz = block->ipar[1];
/*get the A ptrs array*/
A = rpar;
/*get the B ptrs array*/
B = &rpar[A_sz];
...
/*compute the cumsum of the first real parameter array*/
cumsum = 0;
for(i=0;i<A_sz;i++) {
cumsum += A[i];
}
...
/*compute the cumsum of the second real parameter array*/
cumsum = 0;
for(i=0;i<B_sz;i++) {
cumsum += B[i];
}
Note that integer parameters register is only accessible for reading.
#include "scicos_block4.h"
...
int nopar;
int n,m;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get the number of object parameter*/
nopar=block>nopar;
...
/*get number of row of the last object parameter*/
n=block>oparsz[nopar-1];
/*get number of column of the last object parameter*/
m=block>oparsz[2*nopar-1];
...
}
The dimensions of object parameters can be get with the following C macro :
GetOparSize(block,x,1); /*get first dimension of opar*/
GetOparSize(block,x,2); /*get second dimension of opar*/
with x an integer that gives the index of the object parameter, numbered from 1 to nopar.
Scilab | C | |||
Type | Number | Number | Type | Macros |
real matrix | 1 | 10 | double | SCSREAL_COP |
complex matrix | 2 | 11 | double | SCSCOMPLEX_COP |
int32 matrix | 3 | 84 | long int | SCSINT32_COP |
int16 matrix | 4 | 82 | short | SCSINT16_COP |
int8 matrix | 5 | 81 | char | SCSINT8_COP |
uint32 matrix | 6 | 814 | unsigned long int | SCSUINT32_COP |
uint16 matrix | 7 | 812 | unsigned short | SCSUNINT16_COP |
uint8 matrix | 8 | 811 | unsigned char | SCSUINT8_COP |
all others data | -1 | double | SCSUNKNOWN_COP |
The type of object parameter can also be got by the use of the C macro GetOparType(block,x). For i.e, if we want the C number type of the first object parameter, we'll use the following C instructions:
#include "scicos_block4.h"
...
int opartyp_1;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get the number type of the first object parameter*/
opartyp_1 = GetOparType(block,1);
...
}
model.opar=list(int32([1,2;3,4]),[1+%i %i 0.5]);
Then we have two object parameters, one is an 32-bit integer matrix with two rows and two
columns and the second is a vector of complex numbers that can be understand as a matrix
of size 1,3.
At the C computational function level, the instructions block->oparsz[0],
block->oparsz[1], block->oparsz[2], block->oparsz[3] will respectively return the
values 2,1,2,3 and the instructions block->opartyp[0], block->opartyp[1] the values 11 and
84.
block->oparptr will contain then two pointers, and should be viewed as arrays contained data of
object parameter as shown in the following figure :
For i.e., to directly access to the data, the user can use theses instructions :
#include "scicos_block4.h"
...
SCSINT32_COP *ptr_i;
SCSINT32_COP cumsum_i;
SCSCOMPLEX_COP *ptr_d;
SCSREAL_COP cumsum_d;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get the ptrs of an int32 object parameter*/
ptr_i = (SCSINT32_COP *) block->oparptr[0];
/*get the ptrs of a double object parameter*/
ptr_d = (SCSCOMPLEX_COP *) block->oparptr[1];
...
/*compute the cumsum of the int32 matrix*/
cumsum_i = ptr_i[0]+ptr_i[1]+ptr_i[2]+ptr_i[3];
...
/*compute the cumsum of the real part of the complex matrix*/
cumsum_d = ptr_d[0]+ptr_d[1]+ptr_d[2];
...
}
One can also use the set of C macros :
GetRealOparPtrs(block,x), GetImagOparPtrs(block,x),
Getint8OparPtrs(block,x), Getint16OparPtrs(block,x),
Getint32OparPtrs(block,x), Getuint8OparPtrs(block,x),
Getuint16OparPtrs(block,x), Getuint32OparPtrs(block,x)
to have the appropiate pointer of the data to handle (x is numbered from 1 to nopar).
For the previous example that gives :
#include "scicos_block4.h"
...
SCSINT32_COP *ptr_i;
SCSREAL_COP *ptr_dr;
SCSREAL_COP *ptr_di;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get the ptrs of an int32 object parameter*/
ptr_i = Getint32OparPtrs(block,1);
/*get the ptrs of a double object parameter*/
ptr_dr = GetRealOparPtrs(block,2);
ptr_di = GetImagOparPtrs(block,2);
...
}
Note that object parameters register is only accessible for reading.
#include "scicos_block4.h"
...
double x_1;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
x_1=block->x[0];
...
}
Note that on flag=4, user can write some initial conditions in that register.
The pointer of that array can also be retrieve via the C macro GetState(block).
#include "scicos_block4.h"
...
double *x = block->x;
double *xd = block->xd;
...
/* define parameters */
double a = 10;
double b = 28;
double c = 8/3;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
if (flag == 0) {
xd[0] = a*(x[1]-x[0]);
xd[1] = x[1]*(b-x[2])-x[1];
xd[2] = x[0]*x[1]-c*x[2];
}
...
}
#include "scicos_block4.h"
...
double *x = block->x;
double *xd = block->xd;
double *res = block->res;
...
/* define parameters */
double a = 10;
double b = 28;
double c = 8/3;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
if (flag == 0) {
res[0] = - xd[0] + (a*(x[1]-x[0]));
res[1] = - xd[1] + (x[0]*(b-x[2])-x[1]);
res[2] = - xd[2] + (x[0]*x[1]-c*x[2]);
}
...
}
#include "scicos_block4.h"
...
double z_2;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
z_2=block->z[1];
...
}
Note that the state register should be only written for flag=4 and flag=2.
The pointer of that array can also be retrieve via the C macro GetDstate(block).
#include "scicos_block4.h"
...
int noz;
int n,m;
...
/*get the number of object state*/
noz=block>noz;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get number of row of the last object state*/
n=block>ozsz[noz-1];
/*get number of column of the last object state*/
m=block>ozsz[2*noz-1];
...
}
The dimensions of object discrete states can be get with the following C macro :
GetOzSize(block,x,1); /*get first dimension of oz*/
GetOzSize(block,x,2); /*get second dimension of oz*/
with x an integer that gives the index of the discrete object state, numbered from 1 to noz.
Scilab | C | |||
Type | Number | Number | Type | Macros |
real matrix | 1 | 10 | double | SCSREAL_COP |
complex matrix | 2 | 11 | double | SCSCOMPLEX_COP |
int32 matrix | 3 | 84 | long int | SCSINT32_COP |
int16 matrix | 4 | 82 | short | SCSINT16_COP |
int8 matrix | 5 | 81 | char | SCSINT8_COP |
uint32 matrix | 6 | 814 | unsigned long int | SCSUINT32_COP |
uint16 matrix | 7 | 812 | unsigned short | SCSUNINT16_COP |
uint8 matrix | 8 | 811 | unsigned char | SCSUINT8_COP |
all others data | -1 | double | SCSUNKNOWN_COP |
The type of discrete object state can also be got by the use of the C macro GetOzType(block,x). For i.e, if we want the C number type of the first discrete object state, we'll use the following C instructions:
#include "scicos_block4.h"
...
int oztyp_1;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get the number type of the first object state*/
oztyp_1 = GetOzType(block,1);
...
}
model.odstate=list(int32([1,2;3,4]),[1+%i %i 0.5]);
Then we have two discrete object states, one is an 32-bit integer matrix with two rows and two
columns and the second is a vector of complex numbers that can be understand as a matrix
of size 1,3.
At the C computational function level, the instructions block->ozsz[0],
block->ozsz[1], block->ozsz[2], block->ozsz[3] will respectively return the
values 2,1,2,3 and the instructions block->oztyp[0], block->oztyp[1] the values 11 and
84.
block->ozptr will contain then two pointers, and should be viewed as arrays contained data of
discrete object state as shown in the following figure :
For i.e., to directly access to the data, the user can use theses instructions :
#include "scicos_block4.h"
...
SCSINT32_COP *ptr_i;
SCSINT32_COP cumsum_i;
SCSCOMPLEX_COP *ptr_d;
SCSREAL_COP cumsum_d;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get the ptrs of an int32 discrete object state*/
ptr_i = (SCSINT32_COP *) block->ozptr[0];
/*get the ptrs of a double discrete object state*/
ptr_d = (SCSCOMPLEX_COP *) block->ozptr[1];
...
/*compute the cumsum of the int32 matrix*/
cumsum_i = ptr_i[0]+ptr_i[1]+ptr_i[2]+ptr_i[3];
...
/*compute the cumsum of the real part of the complex matrix*/
cumsum_d = ptr_d[0]+ptr_d[1]+ptr_d[2];
...
}
One can also use the set of C macros :
GetRealOzPtrs(block,x), GetImagOzPtrs(block,x),
Getint8OzPtrs(block,x), Getint16OzPtrs(block,x),
Getint32OzPtrs(block,x), Getuint8OzPtrs(block,x),
Getuint16OzPtrs(block,x), Getuint32OzPtrs(block,x)
to have the appropiate pointer of the data to handle (x is numbered from 1 to noz).
For the previous example that gives :
#include "scicos_block4.h"
...
SCSINT32_COP *ptr_i;
SCSREAL_COP *ptr_dr;
SCSREAL_COP *ptr_di;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*get the ptrs of an int32 discrete object state*/
ptr_i = Getint32OzPtrs(block,1);
/*get the ptrs of a double discrete object state*/
ptr_dr = GetRealOzPtrs(block,2);
ptr_di = GetImagOzPtrs(block,2);
...
}
Finally note that the discrete objects state should be only written for flag=4 and flag=2.
#include "scicos_block4.h"
...
void** work=block->work;
...
void mycomputfunc(scicos_block *block,int flag)
{
...
/*initialization*/
if (flag==4) {
/*allocation of work*/
if (*work=scicos_malloc(sizeof(double))==NULL) {
set_block_error(-16);
return;
}
...
}
...
/*other flag treatment*/
...
/*finish*/
else if (flag==5) {
scicos_free(*work);
}
...
}
Note that if a block use a work pointer, it will be called with flag=2 even if
the block don't use discrete states.
The pointer of that array can also be retrieve via the C macro GetWorkPtrs(block).