36 SWIG and Scilab

Scilab is a scientific software package for numerical computations providing a powerful open computing environment for engineering and scientific applications that is mostly compatible with MATLAB.More information can be found at www.scilab.org.

This chapter is intended to give an introduction to using the module. You should also read the SWIG documentation that is not specific to Scilab.Also, there are a dozen or so examples in the Examples/Scilab directory.

36.1 Preliminaries

The current SWIG implemention is based on Scilab 5.1.1. Support for other higher versions has not been tested, nor has support for any OS other than Linux.

36.2 Running SWIG

Let's start with a very simple SWIG interface file:

%module example
%{
#include "example.h"
%}
int gcd(int x, int y);
extern double Foo; 

To build an Scilab module, run SWIG using the -scilab option.

$ swig -scilab example.i 

This creates a C source file example_wrap.c and a interface file builder.sce. The generated C source file contains the low-level wrappers that need to be compiled and linked with the rest of your C application (in this case, the gcd implementation) to create an extension module. And the builder.sce is used to generate the *.so file.

The swig command line has a number of options you can use, like to redirect it's output. Use swig --help to learn about these.

36.2.1 Compiling a dynamic module

Scilab modules are shared objects having the ".so" suffix. Building such a file is usually done with the "exec" command (within Scilab itself) For example,

$ ./scilab
--> exec builder.sce

where builder.sce is the interface file generated by the swig. It looks like the following:

ilib_name = "examplelib";
files = ["example_wrap.c","example.o"];
libs = [];
table = ["gcd","_wrap_gcd";"Foo_set","_wrap_Foo_set";"Foo_get","_wrap_Foo_get";];
ilib_build(ilib_name,table,files,libs);

ilib_build(lib_name,table,files,libs) is used to create shared libraries and to generate a loader file which can be used to dynamically load the shared library into Scilab with addinter.

"exec builder.sce" will produce *.so,and a file called "loader.sce" which contains how to load the module. Loading it into Scilab is then a matter of invoking

Scilab:1> exec loader.sce

36.2.2 Using your module

Assuming all goes well, you will be able to do this:

Scilab:2>gcd(4,6)
ans =  2

Scilab:3>Foo_get
ans =  3

Scilab:4>Foo_set(4);

Scilab:5>Foo_get
ans =  4 

36.3 A tour of basic C wrapping

36.3.1 Modules

The SWIG module directive specifies the name of the Scilab module. If you want to load the module, you'll need a file called "loader.sce" which is usually generated by the command "exec builder.sce". The loader.sce looks as following:

// ------------------------------------------------------
// generated by builder.sce: Please do not edit this file
// ------------------------------------------------------

libexamplelib_path = get_file_path('loader.sce');
list_functions = [             'gcd';
            'Foo_set';
            'Foo_get';
];
addinter(libexamplelib_path+'/libexamplelib.so','libexamplelib',list_functions);
// remove temp. variables on stack
clear libexamplelib_path;
clear list_functions;
clear get_file_path;
// ------------------------------------------------------

addinter (files,spname,fcts) performs incremental linking of a compiled C new Scilab interface routine.

After you run the command "exec loader.sce", you could use the module.

36.3.2 Functions

Global functions are wrapped as new Scilab built-in functions. For example,

%module example
int fact(int n); 

creates a built-in function fact(n) that works exactly like you think it does:

Scilab:1>fact(4)
ant=24 

27.3.3 Global variables

To expose variables, SWIG actually generates two functions, to get and set the value. In this case, Foo_set and Foo_get would be generated. SWIG then automatically calls these functions when you get and set the variable-- in the former case creating a local copy in the interpreter of the C variables, and in the latter case copying an interpreter variables onto the C variable.

scilab:1> exec loader.sce;
scilab:2> c=Foo_get();

scilab:3> Foo_set(4);

scilab:4> c
c =  3

scilab:5> Foo_get()
ans =  4

scilab:6> Foo_set([1,2,3;4,5,6]);

scilab:7> Foo_get()
ans  =
 
    1.    2.    3.  
    4.    5.    6. 
scilab:8> Foo_set([1+2*%i,2+3*%i;3+4*%i,7+8*%i]);

scilab:9> Foo_get()
 ans  =
 
    1. + 2.i    2. + 3.i  
    3. + 4.i    7. + 8.i  

27.3.4 Constants

C constants are not really constant in Scilab. They are actually just a copy of the value into the Scilab interpreter. Therefore they can be changed just as any other value. For example given some constants:

%module example
#define    ICONST      42
#define    FCONST      2.1828
#define    CCONST      'x'
#define    CCONST2     '\n'
#define    SCONST      "Hello World"
#define    SCONST2     "\"Hello World\""

A file called example.sce will be created, which could be interpreted by the scilab. The code in the file is as following:

....
example.ICONST = 42
example.FCONST = 2.1828
example.CCONST = ascii(120)
example.CCONST2 = ascii(10)
example.SCONST = "Hello World"
example.SCONST2 = """Hello World"""
example.EXPR = 42+3*(2.1828)
example.iconst = 37
example.fconst = 3.14
.... 

It is easy to use the C constants after run the command "exec example.sce":

scilab:1> exec example.sce;
scilab:2> example.ICONST
ans= 42
scilab:3> example.FCONST
ans= 2.1828
scilab:4> example.CCONST
ans=x
scilab:5> example.CCONST2
ans=

scilab:6> example.SCONST
ans= Hello World
scilab:7> example.SCONST2
ans= "Hello World"
scilab:8> example.EXPR
ans= 48.5484
scilab:9> example.iconst
ans= 37
scilab:10> example.fconst
ans= 3.14

27.3.5 Enums

The way that deals with the enums is similar to the constants. For example:

%module example
typedef enum  { RED, BLUE, GREEN } color;

A file called example.sce will be created, which could be interpreted by the scilab. The code in the file is as following:

....
color.RED=0;
color.BLUE=color.RED + 1;
color.GREEN=color.BLUE + 1;
.... 

It is easy to use the enums after run the command "exec example.sce":

scilab:1> exec example.sce;
scilab:2> printf("    RED    = %i\n", color.RED);
    RED    = 0

scilab:3> printf("    BLUE    = %i\n", color.BLUE);
    BLUE   = 1

scilab:4> printf("    GREEN    = %i\n", color.GREEN);
    GREEN  = 2

27.3.5 Pointers

Pointers are fully supported by SWIG. One way to deal with the pointers is using the INPUT and OUTPUT typemaps. For example, in order to call C functions as the following:

void sub(int *x, int *y, int *result) {
  *result = *x - *y;
}
int divide(int n, int d, int *r) {
   int q;
   q = n/d;
   *r = n - q*d;
   return q;
}

We could write a interface file:

%module example
%include typemaps.i
extern void sub(int *INPUT, int *INPUT, int *OUTPUT);

%apply int *OUTPUT { int *r };
extern int divide(int n, int d, int *r);

Then run it in Scilab:

scilab:1> r = sub(37,42);
scilab:2> printf("     37 - 42 = %i\n",r);
    37 - 42 = -5

scilab:3> [q,r] = divide(42,37);
scilab:4> printf("     42/37 = %d remainder %d\n",q,r);
    42/37 = 1 remainder 5

From the example above, it is clear that instead of passing a pointer to an object, we only need a real value instead.