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’.

venerdì 7 marzo 2008

sacco dei trucchetti

bag of tricks on line

calling of C/C++ routines from the Windows™ version of Scilab using Microsoft™'s Visual C++ compiler

tratto da qui


Visual C++ by Dave Sidlauskas

This section illustrates the calling of C/C++ routines from the Windows™ version of Scilab using Microsoft™'s Visual C++ compiler. The process is quite simple.

  1. Use VC++ create a DLL containing the C functions.

  2. In Scilab, use link() to load the DLL functions.

  3. Use fort() to run the functions.

In a little more detail:

  1. Use VC++ to create a DLL.

    Start VC++, click FILE, NEW, and select WIN 32 Dynamic Link-Library. Give it a name and location and click OK. Then select Empty DLL and click Finish.

    Prepare a source file and insert it into the project (Project, Add To Project). Then build the project (F7).

    A sample source file is shown below. The declaration extern "C" declspec(dllexport) is critical. Using this, the function name is exported correctly with no name mangling. This type of declaration is covered in the VC++ on-line documentation if you wish more details.

    Also note that C files that are to be executed by a call to fort() are always void, returning no value. Values are returned via pointers in the function parameter list. For example, the parameter *out in matcpy_c is the return value for that function.

    extern "C" _declspec(dllexport) void matset_c(double *mat,
    const int *nrows,
    const int *row,
    const int *col,
    double *val);

    extern "C" _declspec(dllexport) void matcpy_c(const double *in,
    const int *nrow,
    const int *ncol,
    double *out);


    // matset

    // Set element in mat at row and col to val.
    // nrows is number of rows in mat. Shows row
    // and col reference in a C function.
    // REMEMBER: C row or col = Scilab row or col-1.

    void matset_c(double *mat,
    const int *nrows,
    const int *row,
    const int *col,
    double *val)
    {
    mat[*row - 1 + (*col - 1)*(*nrows)] = *val;
    }


    // matcpy

    // Function to copy one matrix to another.

    void matcpy_c(const double *in,
    const int *nrow,
    const int *ncol,
    double *out)
    {
    int row, col;

    for (col = 0; col < *ncol; col++) for (row = 0; row < *nrow; row++) out[row + col*(*nrow)] = in[row + col*(*nrow)]; }
  2. In Scilab, use link to load the DLL functions.

    link("path\filename.dll", "FunctionName", "c")

    The path is wherever you told VC++ to put your output. It is usually something like ProjectName\debug.

    Link uses the WindowsLoadLibrary function to load your DLL. See the VC++ on-line documentation for details.

  3. Use fort() to execute your function.

    Actually it is probably better to prepare a wrapper function to reduce the clutter of fort(). Here is a sample for the matset function above.

    // Wrapper function for calling C language routine matset_c from SciLab

    function mat = matset(mat, row, col, val)
    m = size(mat);
    mat = fort("matset_c",
    mat, 1, "d",
    m(1, 1), 2, "i",
    row, 3, "i",
    col, 4, "i",
    val, 5, "d",
    "out",
    m, 1, "d");
    endfunction

    A sample Scilab session is shown below:

    -->link("d:\vc\sci\debug\sci.dll", "matset_c", "c")
    Linking matset_c
    Link done
    ans =
    0.

    -->getf('E:\scilab\source\ctest.sci');
    -->mat = zeros(5, 5);
    -->matset(mat, 3, 3, 16.71)
    ans =
    ! 0. 0. 0. 0. 0. !
    ! 0. 0. 0. 0. 0. !
    ! 0. 0. 16.71 0. 0. !
    ! 0. 0. 0. 0. 0. !
    ! 0. 0. 0. 0. 0. !

domenica 2 marzo 2008

lanciare scilab in modo batch

tratto da qui


Bien des fois j'utilise Scilab pour effectuer des analyses en cours de journée, ou la nuit, quand je n'utilise pas mon PC.
Voici une méthode simple pour éxécuter un script Scilab en mode automatique.

La commande est assez simple, il s'agit de coder un script Scilab qui effectue les appels aux fonctions utiles aux traitements.
Le script Scilab est éxécuté avec l'option No Windows (-nw) et par l'exécution du script (pas une fonction !), grâce à l'option File (-f).
La commande pour lancer le script est donc la suivante sous Windows :
"C:\Program Files\scilab-4.1.1\bin\scilex" -nw -f MonScript.sce
Le script doit finir par la commande quit.

Prenons l'exemple d'un traitement mtriciel que nous souhaitons sauvegarder dans un fichier.
Voici le script à exécuter (extrait de l'aide Write d'ailleur) :-) :
MonScript.sce :
A=rand(5,3);
write(%io(2),A,'('' | '',3(f10.3,'' | ''))');
if MSDOS then unix('del foo');
else unix('rm -f foo'); end;
write('foo',A)
quit;