C Block structure of a computational function
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 :
The fields, that can be either C pointers or directly data, are then accessible via the *block structure :
This access is a approach and most of users should prefer the approach for facilities purpose.
In the current version of Scicos, the scicos->block structure is defined :
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
#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 appropriate 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.
#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 appropriate 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.
#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** .
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 appropriate 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** .
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 appropriate 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 do not use discrete states. The pointer of that
array can also be retrieve via the C macro
GetWorkPtrs(block)
.