swig/Doc/Manual/Scilab.html
2014-03-20 16:32:07 +01:00

1368 lines
34 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>SWIG and Scilab</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body bgcolor="#ffffff">
<H1><a name="Scilab"></a>37 SWIG and Scilab</H1>
<!-- INDEX -->
<div class="sectiontoc">
<ul>
<li><a href="#Scilab_preliminaries">Preliminaries</a>
<li><a href="#Scilab_running_swig">Running SWIG</a>
<ul>
<li><a href="#Scilab_running_swig_generating_module">Generating the module</a>
<li><a href="#Scilab_running_swig_building_module">Building the module</a>
<li><a href="#Scilab_running_swig_loading_module">Loading the module</a>
<li><a href="#Scilab_running_swig_using_module">Using the module</a>
<li><a href="#Scilab_running_swig_options">Additional command line options</a>
</ul>
<li><a href="#Scilab_wrapping">A tour of basic C/C++ wrapping</a>
<ul>
<li><a href="#Scilab_wrapping_overview">Overview</a>
<li><a href="#Scilab_wrapping_identifiers">Identifiers</a>
<li><a href="#Scilab_wrapping_functions">Functions</a>
<li><a href="#Scilab_wrapping_global_variables">Global variables</a>
<li><a href="#Scilab_wrapping_constants_and_enums">Constants and enumerations</a>
<li><a href="#Scilab_wrapping_pointers">Pointers</a>
<li><a href="#Scilab_wrapping_structs">Structures</a>
<li><a href="#Scilab_wrapping_arrays">Arrays</a>
<li><a href="#Scilab_wrapping_classes">C++ classes</a>
<li><a href="#Scilab_wrapping_templates">C++ templates</a>
<li><a href="#Scilab_wrapping_stl">C++ STL</a>
</ul>
<li><a href="#Scilab_typemaps">Type mappings</a>
<ul>
<li><a href="#Scilab_typemaps_primitive_types">Default primitive type mappings</a>
<li><a href="#Scilab_typemaps_non-primitive_types">Default type mapping for non-primitive types</a>
<li><a href="#Scilab_typemaps_arrays">Arrays</a>
<li><a href="#Scilab_typemaps_pointer-to-pointers">Pointer-to-pointers</a>
<li><a href="#Scilab_typemaps_matrices">Matrices</a>
<li><a href="#Scilab_typemaps_stl">STL</a>
</ul>
<li><a href="#Scilab_module">Module</a>
<ul>
<li><a href="#Scilab_module_structure">Structure</a>
<li><a href="#Scilab_module_interface_file">Interface file</a>
<li><a href="#Scilab_module_building">Building</a>
<li><a href="#Scilab_module_builder">Builder script</a>
<li><a href="#Scilab_module_loader">Loader script</a>
<li><a href="#Scilab_module_initialization">Initialization</a>
</ul>
<li><a href="#Scilab_other_resources">Other resources</a>
</ul>
</ul>
</div>
<!-- INDEX -->
<p>
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 <a href="http://www.scilab.org">www.scilab.org</a>.
</p>
<p>
This chapter explains how to use SWIG for Scilab. After this introduction, you should be able to generate with SWIG a Scilab external module from a C/C++ library.
</p>
<H2><a name="Scilab_preliminaries"></a>37.1 Preliminaries</H2>
<p>
SWIG for Scilab supports Linux. Other operating sytems haven't been tested.
</p>
<p>
Scilab is supported from version 5.3.3.
</p>
<p>
SWIG for Scilab supports C language. C++ is partially supported. See <a href="#Scilab_wrapping">A basic tour of C/C++ wrapping</a> for further details.
</p>
<H2><a name="Scilab_running_swig"></a>37.2 Running SWIG</H2>
<p>
Let's show how to use SWIG for Scilab on a small example, inspired from the "simple" example (found in the <tt>Examples/scilab/simple</tt> directory).
<br>
We want to bind from C a function and a global variable into Scilab.
</p>
<p>
The SWIG interface (in <tt>example.i</tt> file) is as following:
</p>
<div class="code"><pre>
%module Example
%{
double Foo = 3.0;
int gcd(int x, int y) {
int g;
g = y;
while (x > 0) {
g = x;
x = y % x;
y = g;
}
return g;
}
%}
/* A global variable */
double Foo;
/* Compute the greatest common divisor of positive integers */
int gcd(int x, int y);
</pre></div>
<p>
Note: this is not the usual approach to write an interface file, it was used only for tightness and simplicity. See <a href="#Scilab_module">Module</a> to see the usual way to write the interface file.
</p>
<H3><a name="Scilab_running_swig_generating_module"></a>37.2.1 Generating the module</H3>
<p>
The module must be first generated, using the program <tt>swig</tt> and its <tt>-scilab</tt> option.
</p>
<div class="shell"><pre>
$ swig -scilab example.i
</pre></div>
<p>
This command generates two files:
</p>
<ul>
<li>a C source file <tt>example_wrap.c</tt>: the generated C source file contains the wrapping code (and our in case, also the implementation of <tt>gcd</tt>).</li>
<li>a Scilab script <tt>builder.sce</tt>: used to build the shared library (and other files).</li>
</ul>
<p>
Note: if the following error is returned:
<p>
<div class="shell"><pre>
:1: Error: Unable to find 'swig.swg'
:3: Error: Unable to find 'scilab.swg'
</pre></div>
<p>
It may be because the SWIG library is not found. Check the SWIG_LIB environment variable or your SWIG installation.
</p>
<p>
The <tt>swig</tt> command line program has several other options you can use. See <a href="#Scilab_running_swig_options">Additional command line options</a> for further details.
</p>
<H3><a name="Scilab_running_swig_building_module"></a>37.2.2 Building the module</H3>
<p>
In Scilab, the generated builder script <tt>builder.sce</tt> is used to build the generated module:
</p>
<div class="shell"><pre>
$ ./scilab-cli
--&gt; exec builder.sce
</pre></div>
<p>
The build will produce two files:
</p>
<ul>
<li>the shared library <tt>libexample.so</tt>: it has the name of the module in the interface file, and it is prefixed by <tt>lib</tt>.</li>
<li>the loader script <tt>loader.sce</tt>: this script is used to load the shared library in Scilab.</li>
</ul>
<p>
Note: two other files are generated:
</p>
<ul>
<li>the Scilab gateway source file <tt>libexample.c</tt>: it a file used during the build.</li>
<li>the cleaner script <tt>cleaner.sce</tt>: used to clean (delete) the shared library.</li>
</ul>
</p>
<H3><a name="Scilab_running_swig_loading_module"></a>37.2.3 Loading the module</H3>
<p>
This is done by running the following command in Scilab:
</p>
<div class="shell"><pre>
--&gt; exec loader.sce
</pre></div>
<p>
Scilab should output the following messages:
</p>
<div class="shell"><pre>
Shared archive loaded.
Link done.
</pre></div>
<p>
Which means that Scilab has sucessfully loaded the shared library. Its functions and other symbols are now available in Scilab.
</p>
<H3><a name="Scilab_running_swig_using_module"></a>37.2.4 Using the module</H3>
<p>
In Scilab, the function <tt>gcd()</tt> can be used simply like that:
</p>
<div class="targetlang"><pre>
--&gt; gcd(4,6)
ans = 2
</pre></div>
<p>For the <tt>Foo</tt> global variable, the accessors have to be used:
<div class="targetlang"><pre>
--&gt; Foo_get
ans = 3
--&gt; Foo_set(4);
--&gt; Foo_get
ans = 4
</pre></div>
<H3><a name="Scilab_running_swig_options"></a>37.2.5 Additional command line options</H3>
<p>
The following table lists the specific options for Scilab (of <tt>swig</tt> program):
</p>
<table summary="Scilab specific options">
<tr>
<td>-addcflag &lt;opt&gt;</td>
<td>Additional compiler options &lt;opt&gt; to include in build script</td>
</tr>
<tr>
<td>-addldflag &lt;opt&gt;</td>
<td>Additional link options &lt;opt&gt; to include in build script</td>
</tr>
<tr>
<td>-addsrc &lt;files&gt;</td>
<td>Additional comma separated source &lt;files&gt; to include in build script</td>
</tr>
<tr>
<td>-vbl &lt;level&gt;</td>
<td>Sets the build verbose &lt;level&gt; (default 0)</td>
</tr>
<tr>
<td>-buildflags &lt;file&gt;</td>
<td>Uses a Scilab script in &lt;file&gt; to set build flags level</td>
</tr>
<tr>
<td>-nobuilder</td>
<td>Do not generate builder script</td>
</tr>
</table>
<p>
These options can be displayed with:
</p>
<div class="code"><pre>
swig -scilab -help
</pre></div>
<p>
Some examples:
</p>
<div class="shell"><pre>
$ swig -scilab -addcflag -I/usr/includes example.i
$ swig -scilab -addldflag "-lm example.i"
$ swig -scilab -addsrc file1.cxx,file2.cxx,example.i
</pre></div>
</p>
<H2><a name="Scilab_wrapping"></a>37.3 A basic tour of C/C++ wrapping</H2>
<H3><a name="Scilab_wrapping_overview"></a>37.3.1 Overview</H3>
<p>
SWIG for Scilab provides only low-level C interface for Scilab. This means that functions, structs, classes, variables, etc... are interfaced through C functions. These C functions are mapped as Scilab functions.
<p>
<H3><a name="Scilab_wrapping_identifiers"></a>37.3.2 Identifiers</H3>
<p>
In Scilab 5.x, identifier names can be composed of 24 chars maximum (this limitation disappears in future version of Scilab 6.0).
<br>So long function or variable names may be truncated, which can be cause of conflict.
</p>
<p>It happens especially when wrapping structs/classes, for which the wrapping functions name are composed of the struct/class name and field names. In that case, the SWIG <tt>rename</tt> instruction, to choose a different wrapping name, can be useful.
<p>
<H3><a name="Scilab_wrapping_functions"></a>37.3.3 Functions</H3>
<p>
Functions are wrapped as new Scilab built-in functions. For example:
</p>
<div class="code"><pre>
&#037;module example
int fact(int n);
</pre></div>
<p>
Creates a built-in function <tt>fact(n)</tt> in Scilab:
</p>
<div class="targetlang"><pre>
--&gt; fact(4)
ans =
24.
</pre></div>
<H3><a name="Scilab_wrapping_global_variables"></a>37.3.4 Global variables</H3>
<p>
Global variables are manipulated through generated accessor functions.
For example, for a given <tt>Foo</tt> global variable, SWIG actually generates two functions: <tt>Foo_get()</tt> to get the value of <tt>Foo</tt>, and <tt>Foo_set()</tt> to set the value.
These functions are used as following:
</p>
<div class="targetlang"><pre>
--&gt; exec loader.sce;
--&gt; c=Foo_get();
--&gt; Foo_set(4);
--&gt; c
c = 3
--&gt; Foo_get()
ans = 4
</pre></div>
<p>
It works for primitive type variables, but also for other type variables.
For example with two global arrays x and y:
</p>
<div class="code"><pre>
%module example
%inline %{
int x[10];
double y[7];
void initArrays()
{
int i;
for (i = 0; i &lt; 10; i++)
x[i] = 1;
for (i = 0; i &lt; 7; i++)
y[i] = 1.0f;
}
%}
</pre></div>
<p>
It works the same:</p>
<div class="targetlang"><pre>
--&gt; exec loader.sce
--&gt; initArrays();
--&gt; x_get()
ans =
1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
--&gt; y_set([0:6] / 10);
--&gt; y_get()
--&gt;
ans =
0. 0.1 0.2 0.3 0.4 0.5 0.6
</pre></div>
<H3><a name="Scilab_wrapping_constants_and_enums"></a>37.3.5 Constants and enumerations</H3>
<H4><a name="Scilab_wrapping_constants"></a>Constants</H4>
<p>
There is no constant in Scilab. By default, C/C++ constants are wrapped as getter functions. For example for the following constants:
</p>
<div class="code"><pre>
%module example
#define ICONST 42
#define FCONST 2.1828
#define CCONST 'x'
#define CCONST2 '\n'
#define SCONST "Hello World"
#define SCONST2 "\"Hello World\""
</pre></div>
<p>
The following getter functions are generated:
</p>
<div class="targetlang"><pre>
--&gt; exec loader.sce;
--&gt; ICONST_get();
ans= 42
--&gt; FCONST_get();
ans= 2.1828
--&gt; CCONST_get();
ans=x
--&gt; CCONST2_get();
ans=
--&gt; SCONST_get();
ans= Hello World
--&gt; SCONST2_get();
ans= "Hello World"
--&gt; EXPR_get();
ans= 48.5484
--&gt; iconst_get();
ans= 37
--&gt; fconst_get();
ans= 3.14
</pre></div>
<p>
There is another mode in which constants are wrapped as Scilab variables.
The variables are easier to use than functions, but the little drawback is that variables are not constant and so can be modified.
This mode can be enabled/disabled at any time in the interface file with the feature <tt>%scilabconst()</tt> (argument value "1" to enable, "0" to disable).
For example in this mode the previous constants:
</p>
<div class="code"><pre>
%module example
%scilabconst(1);
#define ICONST 42
#define FCONST 2.1828
#define CCONST 'x'
#define CCONST2 '\n'
#define SCONST "Hello World"
#define SCONST2 "\"Hello World\""
</pre></div>
<p>
Are mapped to Scilab variables, with the same name:
</p>
<div class="targetlang"><pre>
--&gt; exec loader.sce;
--&gt; ICONST;
ans= 42
--&gt; FCONST;
ans= 2.1828
--&gt; CCONST;
ans=x
--&gt; CCONST2;
ans=
--&gt; SCONST;
ans= Hello World
--&gt; SCONST2;
ans= "Hello World"
--&gt; EXPR;
ans= 48.5484
--&gt; iconst;
ans= 37
--&gt; fconst;
ans= 3.14
</pre></div>
<H4><a name="Scilab_wrapping_enums"></a>Enumerations</H4>
<p>
The wrapping of enums is quite the same as for constants.
In the default mode, the enums are wrapped as getter functions.
For example on the following enumeration:
</p>
<div class="code"><pre>%module example
typedef enum { RED, BLUE, GREEN } color;
</pre></div>
<p>
A getter function will be generated for each value of the enumeration:
</p>
<div class="targetlang"><pre>
--&gt; exec loader.sce;
--&gt; printf(" RED = %i\n", RED_get());
RED = 0.
--&gt; printf(" BLUE = %i\n", BLUE_get());
BLUE = 1.
--&gt; printf(" GREEN = %i\n", GREEN_get());
GREEN = 2.
</pre></div>
<p>
The feature <tt>%scilabconst()</tt> is also available for enumerations:
</p>
<div class="code"><pre>%module example
%scilabconst(1);
typedef enum { RED, BLUE, GREEN } color;
</pre></div>
<p>
<div class="targetlang"><pre>
--&gt; exec loader.sce;
--&gt; printf(" RED = %i\n", RED);
RED = 0.
--&gt; printf(" BLUE = %i\n", BLUE);
BLUE = 1.
--&gt; printf(" GREEN = %i\n", GREEN);
GREEN = 2.
</pre></div>
</p>
<H3><a name="Scilab_wrapping_pointers"></a>37.3.6 Pointers</H3>
<p>
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:
</p>
<div class="code"><pre>
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;
}
</pre></div>
<p> We could write an interface file:
</p>
<div class="code"><pre>%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);
</pre></div>
<p>Then run it in Scilab:
</p>
<div class="targetlang"><pre>
--&gt; r = sub(37,42);
--&gt; printf(" 37 - 42 = %i\n",r);
37 - 42 = -5
--&gt; [q,r] = divide(42,37);
--&gt; printf(" 42/37 = %d remainder %d\n",q,r);
42/37 = 1 remainder 5
</pre></div>
<p> From the example above, it is clear that instead of passing a pointer to an object,
we only need a real value instead.
</p>
<H3><a name="Scilab_wrapping_structs"></a>37.3.7 Structures</H3>
<p>
A C structure is wrapped through a pointer and getter and setter functions for access to the member variables.
For example of a struct with two members:
</p>
<div class="code"><pre>
%module example
%inline %{
typedef struct {
int x;
int arr[4];
} Foo;
%}
</pre></div>
<p>
Several functions are generated:
<ul>
<li>a creation function <tt>new_Foo()</tt> which returns a pointer to a new created struct <tt>Foo</tt>.</li>
<li>the two getter functions <tt>Foo_x_get()</tt>, <tt>Foo_arr_get()</tt>, to get the values of <tt>x</tt> and <tt>y</tt> for the struct pointer given in parameter</li>
<li>the two setter functions <tt>Foo_x_set()</tt>, <tt>Foo_arr_set()</tt>, to set the values of <tt>x</tt> and <tt>y</tt> for the struct pointer given in parameter.</li>
<li>a destruction function <tt>delete_Foo()</tt> to release the struct pointer.</li>
</ul>
</p>
<p>
Following is an example of use:
</p>
<div class="targetlang"><pre>
--&gt; f = new_Foo();
--&gt; Foo_x_set(f, 100);
--&gt; Foo_x_get(f)
ans =
100.
--&gt; Foo_arr_set(f, [0:3]);
--&gt; Foo_arr_get(f)
ans =
0. 1. 2. 3.
--&gt; delete_Foo(f);
</pre></div>
<p>
Members of a structure that itself are a structure are also accepted and wrapped as a pointer:</p>
</p>
<div class="code"><pre>
%module example
%inline %{
typedef struct {
int x;
} Bar;
typedef struct {
Bar b;
} Foo;
%}
</pre></div>
<p>
<div class="targetlang"><pre>
--&gt; b = new_Bar();
--&gt; Bar_x_set(b, 20.);
--&gt; f = new_Foo();
--&gt; Foo_b_set(f, b);
--&gt; b2 = Foo_b_get(f);
--&gt; Bar_x_get(b2);
ans =
20.
</pre></div>
</p>
<H3><a name="Scilab_wrapping_classes"></a>37.3.8 C++ Classes</H3>
<p>
The classes are wrapped the way as structs, through functions. For example, the following class:
</p>
<div class="targetlang"><pre>
%module example
%inline %{
class Point {
public:
int x,y;
Point(int _x,int _y) : x(_x),y(_y) {}
double distance(const Point& rhs) {
return sqrt(pow(x-rhs.x,2)+pow(y-rhs.y,2));
}
void set(int _x,int _y) {
x=_x;
y=_y;
}
};
%}
</pre></div>
<p>
can be used from Scilab like this:
</p>
<div class="targetlang"><pre>
--&gt; p1 = Point_new(3, 5);
--&gt; p2 = Point_new(1, 2);
--&gt; p1.distance(p2)
ans =
3.6056
--&gt; delete_Point(p1);
--&gt; delete_Point(p2);
</pre></div>
<H3><a name="Scilab_wrapping_templates"></a>37.3.9 C++ Templates</H3>
<p>
Templates are supported. See the SWIG general documentation on how templates are interfaced in SWIG.<br>
An example of templates can be found in <tt>Examples/scilab/templates</tt>.
</p>
<H3><a name="Scilab_wrapping_stl"></a>37.3.10 C++ STL</H3>
<p>
The Standard Template Library (STL) is partially supported. See <a href="#Scilab_typemaps_stl">STL</a> for more details.
</p>
<H2><a name="Scilab_typemaps"></a>37.4 Type mappings</H2>
<H3><a name="Scilab_typemaps_primitive_types"></a>37.4.1 Default primitive type mappings</H3>
<p>
The following table give for each C/C++ primitive type the equivalent Scilab type.
</p>
<div class="table">
<table border="1" sumary="Scilab default primitive type mappings">
<tr>
<td><b>C/C++ type</b></td>
<td><b>Scilab type</b></td>
</tr>
<tr><td>bool</td><td>boolean</td></tr>
<tr><td>char</td><td>string</td></tr>
<tr><td>signed char</td><td>double or int8</td></tr>
<tr><td>unsigned char</td><td>uint8</td></tr>
<tr><td>short</td><td>double or int16</td></tr>
<tr><td>unsigned short</td><td>uint16</td></tr>
<tr><td>int</td><td>double or int32</td></tr>
<tr><td>unsigned int</td><td>uint32</td></tr>
<tr><td>long</td><td>double or int32</td></tr>
<tr><td>unsigned long</td><td>uint32</td></tr>
<tr><td>signed long long</td><td>not supported in Scilab 5.x</td></tr>
<tr><td>unsigned long long</td><td>not supported in Scilab 5.x</td></tr>
<tr><td>float</td><td>double</td></tr>
<tr><td>double</td><td>double</td></tr>
<tr><td>char* or char[]</td><td>string</td></tr>
</table>
</div>
<p>
Notes:
<ul>
<li><tt>Double</tt> type in Scilab is far more used than any integer type.
That's why signed integer values (<tt>short, int, integer, long</tt>) are automatically converted to Scilab <tt>double</tt> values in output of a C function.
Also in input, <tt>double</tt> values are converted from <tt>double</tt> into the appropriate integer type.
Unsigned integers are not concerned by these conversions.
</li>
<li>
When an integer is expected, if the input is a double, it must be an integer, i.e. it must not have any decimal part, otherwise a SWIG value error occurs.
</li>
<li>
In SWIG for Scilab 5.x the <tt>long long</tt> type is not supported since Scilab 5.x does not have a 64-bit integer type.
In that case, SWIG displays an error when wrapping a function that has <tt>long long</tt> type arguments.
</li>
</ul>
</p>
<H3><a name="Scilab_typemaps_non-primitive_types"></a>37.4.2 Default type mappings for non-primitive types</H3>
<p>
The default mapped type for C/C++ non-primitive types is the Scilab pointer. That is the case for exemple for C structs, C++ classes, etc...
</p>
<H3><a name="Scilab_typemaps_arrays"></a>37.4.3 Arrays</H3>
<p>
Typemaps are available by default for arrays. Primitive type arrays are automatically converted from/to Scilab matrices.
Conversion is done also for arrays that are member of a structure or a class.
</p>
<p>
In input, the matrix is usually one-dimensional (it can be either a row or column vector). But it can be also a two-dimensional matrix.
Warning: in Scilab, the values are column-major orderered, unlike in C, in which there are row-major ordered.
</p>
<p>
The type mappings used for arrays is the same for primtive types, described <a href="#Scilab_typemaps_primitive_types">here</a>.
It means that, if needed, a Scilab double vector is converted in input into a C int array.
And this C int array is automatically converted in output to a Scilab double vector.
Note that unlike scalars, no control is done for arrays when a double is converted to integer.
</p>
<p>
</p>
<p>
This example illustrates all this:</p>
<div class="code"><pre>
%module example
%#include &lt;stdio.h&gt;
%inline %{
void printArray(int values[], int len) {
int i = 0;
for (i = 0; i &lt; len; i++) {
printf("%s %d %s", i==0?"[":"", values[i], i==len-1?"]\n":"");
}
}
%}
</pre></div>
<p>
<div class="targetlang"><pre>
--&gt; printArray([0 1 2 3], 4)
[ 0 1 2 3 ]
-->printArray([0.2; -1.8; 2; 3.7], 4)
[ 0 -1 2 3 ]
--&gt; printArray([0 1; 2 3], 4)
[ 0 2 1 3 ]
--&gt; printArray([0; 1; 2; 3], 4)
[ 0 1 2 3 ]
<pre></div>
</p>
<H3><a name="Scilab_typemaps_pointer-to-pointers"></a>37.4.4 Pointer-to-pointers</H3>
<p>
There is no specific typemap for pointer-to-pointers, they are are mapped as pointers in Scilab.
</p>
<p>
Pointer-to-pointers are sometimes used to implement matrices in C. Following is a an example of this:
</p>
<div class="code"><pre>
%module example
%inline %{
// Returns the matrix [1 2; 3 4];
double **create_matrix() {
double **M;
int i;
M = (double **) malloc(2 * sizeof(double *));
for (i = 0; i &lt; 2; i++) {
M[i] = (double *) malloc(2 * sizeof(double));
M[i][0] = 2 * i + 1;
M[i][1] = 2 * i + 2;
}
return M;
}
// Gets the item M(i,j) value
double get_matrix(double **M, int i, int j) {
return M[i][j];
}
// Sets the item M(i,j) value to be val
void set_matrix(double **M, int i, int j, double val) {
M[i][j] = val;
}
// Prints a matrix (2,2) to console
void print_matrix(double **M, int nbRows, int nbCols) {
int i, j;
for (i = 0; i &lt; 2; i++) {
for (j = 0; j &lt; 2; j++) {
printf("%3g ", M[i][j]);
}
printf("\n");
}
}
%}
</pre></div>
<p>
These functions are used like this in Scilab:
</p>
<div class="targetlang"><pre>
--&gt; m = create_matrix();
--&gt; print_matrix(m);
1. 2.
3. 4.
--&gt; set_matrix(m, 1, 1, 5.);
--&gt; get_matrix(m, 1, 1)
ans =
5.
</pre></div>
<H3><a name="Scilab_typemaps_matrices"></a>37.4.5 Matrices</H3>
<p>
The library <tt>matrix.i</tt> provides a set of typemaps which can be useful when working with one-dimensional and two-dimensional matrices.
</p>
<p>
To use that library, just include it in the interface file:
</p>
<div class="code"><pre>
%include matrix.i
</pre></div>
<p>
Several typemaps are available for the common Scilab matrix types:
<ul>
<li><tt>double</tt></li>
<li><tt>int</tt></li>
<li><tt>char *</tt></li>
<li><tt>bool</tt></li>
</ul>
</p>
<p>
For example: for a matrix of <tt>int</tt>, we have the typemaps, for input:
<ul>
<li><tt>(int *matrixIn, int matrixInRowCount, int matrixInColCount)</tt></li>
<li><tt>(int matrixInRowCount, int matrixInColCount, int *matrixIn)</tt></li>
<li><tt>(int *matrixIn, int matrixInSize)</tt></li>
<li><tt>(int matrixInSize, int *matrixIn)</tt></li>
</ul>
</p>
<p>
and output:
<ul>
<li><tt>(int **matrixOut, int *matrixOutRowCount, int *matrixOutColCount)</tt></li>
<li><tt>(int *matrixOutRowCount, int *matrixOutColCount, int **matrixOut)</tt></li>
<li><tt>(int **matrixOut, int *matrixOutSize)</tt></li>
<li><tt>(int *matrixOutSize, int **matrixOut)</tt></li>
</ul>
</p>
<p>Following is an exemple using that typemaps:</p>
<div class="code"><pre>
%module example
%include matrix.i
%apply (int *matrixIn, int matrixInRowCount, int matrixInColCount) { (int *matrix, int matrixNbRow, int matrixNbCol) };
%apply (int **matrixOut, int *matrixOutRowCount, int *matrixOutColCount) { (int **outMatrix, int *outMatrixNbRow, int *outMatrixNbCol) };
%inline %{
void absolute(int *matrix, int matrixNbRow, int matrixNbCol,
int **outMatrix, int *outMatrixNbRow, int *outMatrixNbCol) {
int i, j;
*outMatrixNbRow = matrixNbRow;
*outMatrixNbCol = matrixNbCol;
*outMatrix = malloc(matrixNbRow * matrixNbCol * sizeof(int));
for (i=0; i &lt; matrixNbRow * matrixNbCol; i++) {
(*outMatrix)[i] = matrix[i] &gt; 0 ? matrix[i]:-matrix[i];
}
}
%}
</pre></div>
<p>
<div class="targetlang"><pre>
--&gt; absolute([-0 1 -2; 3 4 -5])
ans =
0. 1. 2.
3. 4. 5.
</pre></div>
</p>
<p>
The remarks made for arrays remain here:
<ul>
<li>The values of matrices in Scilab are column-major orderered, be careful while reading/writing processing data.</li>
<li>There is no control while converting <tt>double</tt> values to integers, <tt>double</tt> values are truncated without any check.</li>
</ul>
</p>
<H3><a name="Scilab_typemaps_stl"></a>37.4.6 STL</H3>
<p>
The STL library wraps some containers defined in the STL (Standard Template Library), so that they can be manipulated in Scilab.
This library provides also the typemaps to pass them as input/argument arguments of functions.
<p>
<p>
The list of wrapped sequence containers are:
<ul>
<li><tt>std::vector</tt></li>
<li><tt>std::list</tt></li>
<li><tt>std::deque</tt></li>
</ul>
</p>
<p>
And for associative containers:
<ul>
<li><tt>std::set</tt></li>
</ul>
<p>
<p>
The typemaps are available for the following types:
</p>
<ul>
<li><tt>double</tt></li>
<li><tt>int</tt></li>
<li><tt>string</tt></li>
<li><tt>bool</tt></li>
<li><tt>pointer</tt></li>
</ul>
<p>
Container of other item types are not supported. Using them does not break compilation, but provokes a runtime error.
</p>
<p>
To use the STL, first the library has to be included in the SWIG interface file:
</p>
<div class="code"><pre>
%include stl.i
</pre/></div>
<p>Then for each container used, the template has to be instantied, in the <tt>std</tt> namespace:
<div class="code"><pre>
namespace std {
%template(IntVector) vector&lt;int&gt;;
%template(DoubleVector) vector&lt;double&gt;;
}
</pre></div>
<p>
At last, the module initialization function has to be executed first in Scilab, so that all that types are known by Scilab.
See <a href="#Scilab_module_initialization">37.5.6</a> for more details.
</p>
<H4><a name="Scilab_sequence_containers"></a>Sequence containers</H4>
<p>
Because in Scilab matrices exist for basic types only, a sequence container of pointers is mapped to a Scilab list.
For other item types (double, int, string...) the sequence container is mapped to a Scilab matrix.
<p>
<p>
This example shows how to create in Scilab a vector (of <tt>int</tt>), add some values in that vector, and pass it as an argument of a function.
It shows also (thanks to the typemaps) that we can also pass directly a matrix of values to the function:
</p>
<div class="code"><pre>
%module example
%include stl.i
namespace std {
%template(IntVector) vector&lt;int&gt;;
}
%{
#include &lt;numeric&gt;
%}
%inline %{
double average(std::vector&lt;int&gt; v) {
return std::accumulate(v.begin(), v.end(), 0.0) / v.size();
}
%}
</pre></div>
<p>
<div class="targetlang"><pre>
--&gt; example_Init();
--&gt; v = new_IntVector();
--&gt; for i = 1:4
--&gt; IntVector_push_back(v, i);
--&gt; end;
--&gt; average(v)
ans =
2.5
--gt; average(int32([0 1 2 3]))
ans =
2.5
--&gt; delete_IntVector();
</pre></div>
</p>
<H4><a name="Scilab_set_containers"></a>Associative containers</H4>
<p>
A <tt>set</tt> is mapped from/to a Scilab list.
</p>
<p>
In the following example, a set of struct (<tt>Person></tt>) is wrapped.
It is processed in a function, and as expected, the result is converted to a list of pointers in Scilab:
<div class="code"><pre>
%module example
%include stl.i
%{
#include &lt;string&gt;
%}
%inline %{
struct Person {
Person(std::string _name, int _age) : name(_name), age(_age) {};
std::string name;
int age;
};
typedef Person* PersonPtr;
%}
namespace std {
%template(PersonPtrSet) set&lt;PersonPtr&gt;;
}
%inline %{
std::set&lt;PersonPtr&gt; findPersonsByAge(std::set&lt;PersonPtr&gt; persons, int minAge, int maxAge) {
std::set&lt;PersonPtr&gt; foundPersons;
for (std::set&lt;PersonPtr&gt;::iterator it = persons.begin(); it != persons.end(); it++) {
if (((*it)-&gt;age &gt;= minAge) && ((*it)-&gt;age &lt;= maxAge)) {
foundPersons.insert(*it);
}
}
return foundPersons;
}
%}
</pre></div>
<p>
<div class="targetlang"><pre>
--&gt; example_Init();
--&gt; joe = new_Person("Joe", 25);
--&gt; susan = new_Person("Susan", 32);
--&gt; bill = new_Person("Bill", 50);
--&gt; p = new_PersonPtrSet();
--&gt; PersonPtrSet_insert(p, susan);
--&gt; PersonPtrSet_insert(p, joe);
--&gt; PersonPtrSet_insert(p, bill);
--&gt; l = findPersonsByAge(p, 20, 40);
--&gt; size(l)
ans =
2.
--&gt; Person_name_get(l(1))
ans =
Susan
--&gt; Person_name_get(l(2))
ans =
Joe
--&gt; delete_PersonPtrSet(p);
</pre></div>
<p>
<H2><a name="Scilab_module"></a>37.5 Module</H2>
<p>
In this part we describe how may be structured a module, how to build it, and give some details about the generated scripts.
</p>
<H3><a name="Scilab_module_structure"></a>37.5.1 Structure</H3>
<p>
Usually, one module is created to bind one library. Each library to be wrapped comes with the following files:
</p>
<ul>
<li>header files (<tt>.h</tt>, <tt>.hpp</tt>,...) of the module, or of a third party library.</tt></li>
<li>source files (<tt>.c</tt>, <tt>.cpp</tt>,...).</tt></li>
<li>some third party libraries (<tt>.so</tt>) to link with.</tt></li>
</ul>
<H3><a name="Scilab_module_interface_file"></a>37.5.2 Interface file</H3>
<p>
Each module needs one interface file. Multi modules in an interface file are not supported.
</p>
<p>
The module interface file begins by declaring the module name, then the wrapping declarations follow.
It is often easier to include the whole header of libray to wrap. Then the interface file typically looks like this:
</p>
<div class="code"><pre>
%module [module_name]
%{
#include [header]
....
%}
#include [header]
....
</pre></div>
<H3><a name="Scilab_module_building"></a>37.5.3 Building</H3>
<p>
SWIG for Scilab builds dynamic modules. This means shared libaries are built (.so), which are dynamically linked by Scilab.
</p>
<p>
To generate the code and the builder script, the following options may be used with <tt>swig</tt>:
</p>
<ul>
<li><tt><b>addsrc</b></tt>: to add in the compilation source files</li>
<li><tt><b>addcflag</b></tt>: to set the header include paths</li>
<li><tt><b>addldflag</b></tt>: to set the third party library paths and names</li>
</ul>
<p>
The <tt>swig</tt> command to use may be something like this:
</p>
<div class="shell"><pre>
swig -scilab -addcflag "-I[inc_path]..." -addsrc [source],... -addldflag "-L[lib_path] -l[lib_name]" [module_name].i
</pre></div>
<H3><a name="Scilab_module_builder"></a>37.5.4 Builder script</H3>
<p>
<tt>builder.sce</tt> is the script file generated by SWIG. It contains the following code:
</p>
<div class="code"><pre>
ilib_name = "examplelib";
files = ["example_wrap.c"];
libs = [];
table = ["gcd","_wrap_gcd";"Foo_set","_wrap_Foo_set";"Foo_get","_wrap_Foo_get";];
ilib_build(ilib_name,table,files,libs);
</pre></div>
<p>
<tt>ilib_build(lib_name,table,files,libs)</tt> 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 <tt>addinter</tt>.
</p>
<ul>
<li><tt><b>ilib_name</b></tt>: a character string, the generic name of the library without path and extension.</li>
<li><tt><b>files</b></tt>: string matrix giving objects files needed for shared library creation.</li>
<li><tt><b>libs</b></tt>: string matrix giving extra libraries needed for shred library creation.</li>
<li><tt><b>table</b></tt>: two column string matrix giving the table of pairs 'scilab-name', 'interface name'.</li>
</ul>
<H3><a name="Scilab_module_loader"></a>37.5.5 Loader script</H3>
<p>
The loader script <tt>loader.sce</tt> script looks as following:
</p>
<div class="code"><pre>
// ------------------------------------------------------
// 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;
// ------------------------------------------------------
</pre></div>
<p>
<tt>addinter(files,spname,fcts)</tt> performs dynamic linking of a compiled C new Scilab interface routine.
</p>
<ul>
<li><tt><b>files</b></tt>: a character string or a vector of character string contain object files used to define the new Scilab interface routine (interface code, user routines or libraries, system libraries).</li>
<li><tt><b>spname</b></tt>: a character string. Name of interface routine entry point.</li>
<li><tt><b>fcts</b></tt>: vector of character strings. The name of new Scilab function implemented in the new interface.</li>
</ul>
<H3><a name="Scilab_module_initialization"></a>37.5.6 Initialization</H3>
<p>
A built-in Scilab function is generated for the wrapped module.
This function is used to initialize the module SWIG runtime (which is necessary when working with the STL), or to import in Scilab some wrapped constants and variables.
So it is recommanded to execute this function at first, each time the wrapped library has to be used.
</p>
<p>
The function has the name _Init() and is prefixed by the module name.
For example, to init the module <tt> example</tt> :
</p>
<div class="targetlang"><pre>
--&gt; example_Init();
</pre></div>
<H2><a name="Scilab_other_resources"></a>37.6 Other resources</H2>
<ul>
<li>Examples can be found in the <tt>Examples/scilab directory</tt>, and they cover the different cases of wrapping.</li>
<li>The test suite in the <tt>Examples/test-suite/scilab</tt> can be another source of wrapping use cases.</li>
</ul>