next up previous
Next: About this document ...

Comment interfacer Scilab avec du code C

So_penible_animation

2004

Le but de ce tutorial est de montrer comment construire et interfacer du code C pour l'utiliser avec Scilab. Les interfaces sont écrites à la main en début du code C.

On va présenter deux exemples triviaux. Le premier fait la somme de deux entiers et renvoie le résultat. Le second permet d'utiliser de manipuler des matrices de Scilab au code C et réciproquement (fonctions ReadMatrix et WriteMatrix), ce qui est intéressant pour pouvoir tirer parti des avantages de chaque environement : calcul et représentation matricielle sous Scilab (pas de pointeurs ;-P), rapidité du code C.

Présentons d'abord le premier programme interface_ma_fonction_C.c

#include <stdio.h>
#include <math.h>
#include "/usr/lib/scilab-3.0/routines/machine.h"
#include "/usr/lib/scilab-3.0/routines/stack-c.h"


/*--------------------------------------------------------
 * interface_ma_fonction_C: interface for tutorial C-function 
 *     should provide a+b at Scilab level 
 *--------------------------------------------------------*/


extern void F2C(ma_fonction_C) __PARAMS((int *a, int *b, int *resultat));


void interface_ma_fonction_C(fname)
     char *fname;
{

 int l1,mi,ni,l2,mj,nj,l3,msortie=1,nsortie=1;
 int minlhs=1, maxlhs=1, minrhs=2, maxrhs=2;

  /* Check number of inputs (rhs=2) and outputs (lhs=1) */
  CheckRhs(minrhs,maxrhs) ;
  CheckLhs(minlhs,maxlhs) ;
 
  GetRhsVar(1, "i", (mi=1,&mi), (ni=1,&ni), &l1);   // a
  GetRhsVar(2, "i", (mj=1,&mj), (nj=1,&nj), &l2);   // b
  CreateVar(3, "i",&msortie, &nsortie, &l3);        // resultat
  
   /* Call the function */

    C2F(ma_fonction_C)(istk(l1),istk(l2),istk(l3));
      
  /*  Return variables  */
  LhsVar(1) = 3;
  return 0;
}

//----------------------------------------------------------------------------------------------------
///////////////////// Fin de l'interface -------------------------------------------------------------
//----------------------------------------------------------------------------------------------------

//*****  Debut du programme ****//



void F2C(ma_fonction_C)(astar,bstar,resultatstar)
     int *astar,*bstar,*resultatstar;
   
{

  resultatstar[0]=astar[0]+bstar[0];
  // printf(" calcul fait resultat= %d",resultatstar[0]); /// les printfs s'affichent dans le terminal ///
  return(0);
}

Pour la partie interface, on constate que les variables sont passées sous forme de pointeurs. On doit vérifier le nombre et la taille des variables d'entrée et de sortie CheckRhs, CheckLhs, GetRhsVar, CreateVar (les paramètres associés sont des paramètres de type, de taille (ligne et colonne) et d'adresse. Le résultat est désigné en précisant le numéro de la variable de sortie LhsVar(1) = 3. L'appel de la fonction fait intervenir le type de la variable par le biais de istk(adresse) pour des entiers (sstk pour des floats) associé respectivement à ``i'' dans le GetRhsVar (``r'' pour les floats).

Le second programme est structurellement identique sauf qu'il ne renvoie pas de résultat. Il permet cependant d'utiliser des fonctions permettant de lire ou d'écrire une matrice directement dans Scilab.

#include <stdio.h>
#include <math.h>
#include "/usr/lib/scilab-3.0/routines/machine.h"
#include "/usr/lib//scilab-3.0/routines/stack-c.h"


/*--------------------------------------------------------
 * interface_ma_fonction_C2: interface for tutorial C-function 
 *      
 *--------------------------------------------------------*/


extern void F2C(ma_fonction_C2b) __PARAMS((int *a, int *b, int *taille));

void interface_ma_fonction_C2b(fname)
     char *fname;
{

  int l1,mi,ni,l2,mj,nj,l3,mk,nk,l4,msortie=1,nsortie=1;
  int minlhs=0, maxlhs=0, minrhs=3, maxrhs=3;

  /* Check number of inputs (rhs=3) and outputs (lhs=0) */
  CheckRhs(minrhs,maxrhs) ;
  // CheckLhs(minlhs,maxlhs) ;  // not needed here (because no output)
  

  GetRhsVar(1, "i", (mi=1,&mi), (ni=1,&ni), &l1);   // a
  GetRhsVar(2, "i", (mj=1,&mj), (nj=1,&nj), &l2);  //  b
  GetRhsVar(3, "i", (mk=1,&mk), (nk=1,&nk), &l3);  //  taille


   /* Call the function */
 
    C2F(ma_fonction_C2b)(istk(l1),istk(l2),istk(l3));


   return(0);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////// Fin de l'interface ////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////

//**** Debut du programme ****//

#include <stdio.h>
#include <math.h>
#include "/usr/lib/scilab-3.0/routines/machine.h"
#include "/usr/lib/scilab-3.0/routines/stack-c.h"



void F2C(ma_fonction_C2b)(astar,bstar,taillestar)
     int *astar,*bstar,*taillestar;
   
{

int  taille,*resultatstar;
 taille=taillestar[0];
double NEWMATRICE[taille][taille];

  resultatstar[0]=astar[0]+bstar[0];   
 
   // Lecture de la matrice "NEWMATRICE" dans l'environement Scilab
   ReadMatrix("NEWMATRICE",&taillestar[0], &taillestar[0], &NEWMATRICE[0][0]);
 
   NEWMATRICE[0][0]=4;  // modification d'une donnee

   // Ecriture de la matrice NEWMATRICE2 dans l'environement Scilab (qui a pour valeur NEWMATRICE modifiee
   WriteMatrix("NEWMATRICE2", &taillestar[0], &taillestar[0], &NEWMATRICE[0][0]);

return(0);

}

Maintenant la compilation :

On execute dans Scilab le programme builder.sce qui contient :

// This is the builder.sce 
// must be run from this directory 

ilib_name  = 'libtutorial' 		// interface library name 
files = ['interface_ma_fonction_C.o','interface_ma_fonction_C2b.o']     // objects files 
					// 
libs  = [] 				// other libs needed for linking
table = [ 'ma_fonction_C', 'interface_ma_fonction_C';
   'ma_fonction_C2b', 'interface_ma_fonction_C2b'];		// table of (scilab_name,interface-name) 
                                                        	// for fortran coded interface use 'C2F(name)'
// do not modify below 
// ----------------------------------------------
ilib_build(ilib_name,table,files,libs)

Si tout se passe bien on a

-->exec builder.sce;
 ilib_name  =
 
 libtutorial   
 files  =
 
!interface_ma_fonction_C.o  interface_ma_fonction_C2b.o  !
 libs  =
 
     []
   generate a gateway file
   generate a loader file
   generate a Makefile: Makelib
   running the makefile
   compilation of interface_ma_fonction_C
   compilation of interface_ma_fonction_C2b
   building shared library (be patient)

Un certain nombre de fichiers ont été générés

  interface_ma_fonction_C2b.lo
  interface_ma_fonction_C2b.o
  interface_ma_fonction_C.lo
  interface_ma_fonction_C.o
  .libs
  libtutorial.so
  libtutorial.a
  libtutorial.c
loader.sce
  Makelib

Le plus important est le loader.sce qui va nous permettre déxecuter les fonctions son contenu est le suivant :

// generated by builder.sce: Please do not edit this file
// ------------------------------------------------------
libtutorial_path=get_file_path('loader.sce');
functions=[ 'ma_fonction_C';
            'ma_fonction_C2b';
];
addinter(libtutorial_path+'/libtutorial.so','libtutorial',functions);

Le programme Scilab proprement dit :

// Ce programme Scilab permet d'utiliser des fonctions C
// interface_ma_fonction_C.c et interface_ma_fonction_C2.c

/// Chargement
exec loader.sce;    /// affiche : -->   shared archive loaded

a=2;
b=3;


/// 1er exemple
/// Appel de ma_fonction_C

resu=ma_fonction_C(a,b)  // donne 5  ;-)


/// 2eme exemple

NEWMATRICE=ones(2,2);   // creation d'une matrice 2x2 contenant des 1    
taille=2;          // taille de la matrice

/// Appel de ma_fonction_C2b

ma_fonction_C2b(a,b,taille);  // les variables a et b ne servent a
rien ici !!! 
                            /// on verifie que dans Scilab une nouvelle matrice  NEWMATRICE2 a ete creee
			   ///  et qu'elle contient un 4  et trois 1 



\\fin du programme

En conclusion, ce n'est pas si difficile à faire que d'utiliser du code C dans scilab. L'écriture manuelle des interfaces n'est pas très difficile à condition cependant de bien sentir comment les choses fonctionnent car les exemples donnés ne sont pas si explicite que ça ! Le reproche que je peux adresser sur ce point à Scilab est par exemple de ne pas décrire comment utiliser un appel d'une fonction C dans une autre fonction C, même si en trifouillant un peu on arrive à faire une fonction récursive (factorielle)1 . D'autres parts la multiplicité des méthodes diverses intersci, ... et le peu de documentation sont un gros manque.

Voilà,
That's all, Folks !




next up previous
Next: About this document ...
lepage 2004-09-25