SCI/examples/interface-tour-so.
Pour que l'exemple soit plus réaliste nous allons interfacer deux fonctions, la fonction geom que nous avons vu précédemment et la fonction système srand48 qui permet d'initialiser le générateur aléatoire drand48. La fonction système srand48 ne renvoie pas de valeur et admet pour argument un entier, voila son interface :
int intsrand48(char *fname) { int l1, m1, n1; CheckRhs(1,1); CheckLhs(0,1); GetRhsVar(1, "d", &m1, &n1, &l1); if ( m1*n1 != 1 ) { cerro("Erreur: srand48 attend un argument scalaire"); return 0; } srand48((long int) *stk(l1)); LhsVar(1) = 0; /* pas de valeur renvoyée */ return 0; }
Nous avons donc deux fonctions à interfacer et on supposera que les codes C correspondants sont écrits dans un unique fichier intgeom.c (contient intgeom, geom et intsrand48) . On notera qu'il n'y a en fait aucune contrainte sur la répartition des fonctions dans les fichiers. Il faut maintenant charger ces codes dans Scilab pour définir deux nouvelles primitives geom et srand48.
Pour cela, il faut compiler le code, le charger dynamiquement (en chargeant une librairie partagée .so sous Unix ou .dll sous Windows ) et indiquer les nom Scilab (geom et srand48) que l'on veut donner aux fonctions dont les codes sont interfacés par intgeom et intsrand48.
Tout cela va pouvoir s'effectuer depuis Scilab d'une façon indépendante du système hôte (Unix, Windows), des compilateurs disponibles, etc, de la façon suivante. Au moyen d'un éditeur de texte on va constituer un fichier de nom builder.sce. Ce nom est canonique et un utilisateur qui rencontre un fichier de nom builder.sce sait qu'il faut exécuter un tel fichier pour configurer une contribution, un interface, etc ....
// This is the builder.sce // must be run from this directory ilib_name = 'libealea' // interface library name // objects files files = ['intgeom.o']; libs = [] // other libs needed for linking // table of (scilab_name,interface-name) // for fortran coded interface use 'C2F(name)' table =['geom', 'intgeom'; 'srand48','intsrand48']; // do not modify below // ---------------------------------------------- ilib_build(ilib_name,table,files,libs)
Une base de départ pour construire le fichier builder.sce est le fichier d'exemple
SCI/examples/interface-tutorial-so/builder.sce
que l'on peut facilement adapter à un nouvel interfaçage.
Dans ce fichier on trouve les informations suivantes :
Il suffit alors de faire exécuter ce fichier par Scilab (il est impératif pour se faire que le répertoire courant de Scilab soit le répertoire ou se trouve le fichier builder.sce) pour créer une librairie partagée et créer un fichier loader.sce qui permettra de charger la librairie dans Scilab.
-->exec builder.sce -->ilib_name = 'libalea'; // interface library name -->files = ['intgeom.o'] // objects files -->libs = [] // other libs needed for linking -->table = [ 'geom', 'intgeom'; // table of (scilab_name,interface-name) --> 'srand48','intsrand48']; -->// do not modify below -->// ---------------------------------------------- -->ilib_build(ilib_name,table,files,libs); generate a gateway file generate a loader file generate a Makefile: Makelib running the makefile
Après l'exécution de ce fichier, de nouveaux fichiers sont crées dans le répertoire courant.
Le plus important d'entre eux est le fichier loader.sce. Il permet le chargement dans Scilab de la nouvelle librairie au moyen de la fonction addinter. En pratique on exécute donc une fois builder.sce pour compiler la librairie puis à chaque nouvelle session Scilab on exécute loader.sce pour charger la librairie (noter que le chargement peut être effectué de n'importe où, il n'est pas nécessaire de se trouver dans le répertoire de loader.sce pour l'exécuter).
// appel du loader qui est dans un répertoire distant -->exec SCI/contrib/geom/loader.sce -->// generated by builder.sce: Please do not edit this file -->// ------------------------------------------------------ -->libalea_path=get_file_path('loader.sce'); -->functions=[ 'geom'; --> 'srand48'; -->]; -->addinter(libalea_path+'/libalea.so','libalea',functions); Loading shared executable addinter-linux-so//libalea.so shared archive loaded Linking libalea (in fact libalea_) Interface 0 libalea
Citons pour information les autres fichiers générés. On trouve un fichier libalea.c appelé ``gateway''. Il contient une procédure appelée ``procédure de gestion des interfaces''. Elle sert d'aiguillage pour gérer la table de correspondance table.
On trouve également un fichier Makelib qui est un fichier Makefile qui dépend du système hôte et de l'environnement de compilation (Unix, Windows/Visual C++, Windows/Absoft). Il permet la création de la librairie partagée.
Il ne reste plus qu'à tester cette nouvelle primitive geom avec le petit script qui suit. On compare graphiquement (Figure 6) l'histogramme empirique obtenu par simulation et celui donnée par la théorie
-->n=10000; pr=0.2 ; -->y=geom(1,n,pr); // appel de la nouvelle primitive -->N=20; i=0:N; // tests des résultats -->z=[]; for i1=i, z=[z,size(find(y==i1),"*")];end -->plot2d3("onn",i',z'/n,[1,3],"161","Simulation"); -->zt=0;for i1=1:N; zt=[zt,pr*(1-pr)^(i1-1)];end -->plot2d1("onn",i',zt',[-2,6],"100","Theorie");
Figdir