sabato 18 ottobre 2008

Writing a Scilab-callable C routine

tratto da qui


Phoenix and Scilab/C Interfacing

August 9th, 2005 ·

Writing a Scilab-callable C routine

As is the case with most instances of foreign function interfacing, your C function
should be `wrapped’ by another function which does all kinds of nitty-gritty
stuff to massage the high-level language datatypes (like lists) to simple C types.
Fortunately, Scilab comes with a program called `intersci’ which creates the
wrapper functions automagically from a text file with some rather simple
interface specifications. Let’s say we wish to write a function which takes in two
numbers and returns its sum. Here is the C function (in a file called add.c):

int add_(int *a, int *b, int *c)

{
*c = *a + *b;
return 0;
}

And here is the interface specification (in a file add_wrap.desc):

add a b
a vector 1
b vector 1
c vector 1

add a b c
a integer
b integer
c integer

out sequence c

The first part of the interface spec specifies what the Scilab function takes as
arguments (a and b, both vectors of length 1). The second part specifies what the
C function takes as arguments (a, b and c, all of which should be pointers to integers,
but which are simply written as `integer’ in the interface spec). The third part says
that `c’ is an output variable, ie, a value `returned’ from the Scilab function.
Note that the address of the object to be returned from the Scilab function is passed as an argument
to the C function. You visualize a Scilab invocation:

c = add(a, b)

getting transformed to a C function invocation of the form:

add(&a, &b, &c);

Here are the steps to make this C function Scilab callable:

  1. Run the command `intersci-n’ with add_wrap.desc as argument. You should
    see several files, two of which are `add_wrap.c’ and `add_wrap_builder.sce’.
  2. Run scilab and type the following at the Scilab prompt:
    files = ['add.o', 'add_wrap.o']
    libs = []
    exec add_wrap_builder.sce
    exec loader.sce

Now you can invoke add(1,2) at the Scilab prompt and you will get the proper answer.
(Note that Scilab doesn’t differentiate between a 1 element vector and a scalar
quantity; thus [1] is same as 1).

Adding two vectors

Here is another simple example. Our C function is:

int addvect_(int *n, double *a, double *b, double *c)
{
int i;
for(i = 0; i < *n; i++) c[i] = a[i] + b[i]; return 0; }

The interface spec looks like this:

addvect a b
a vector n
b vector n
c vector n

addvect n a b t
n integer
a double
b double
c double

out sequence c
********************

We can call addvect from the Scilab prompt as shown below:

addvect([1,2,3], [4,5,6])

Returning two vectors

Here is a sample C function:

int addmulvect_(int *n, double *a, double *b, double *c, double *d)
{
int i;
for(i = 0; i < *n; i++) c[i] = a[i] + b[i]; for(i = 0; i < *n; i++) d[i] = a[i] * b[i]; return 0; }

And here is the interface description:

addmulvect a b
a vector n
b vector n
c vector n
d vector n

addmulvect n a b c d
n integer
a double
b double
c double
d double

out sequence c d

The function can be called like this:

[p, q] = addmulvect([1,2,3], [4,5,6])

We note that this function returns two vectors which get stored
in `p’ and `q’.