Audela |
![]() |
Nous avons vu que la fonction
de Tcl permet d'ajouter une nouvelle fonction. Cette nouvelle fonction peut être vue comme une macro qui rassemble un enchaînement de fonctions plus simples. S'il est champion en exécution de scripts, il faut reconnaître que Tcl ne brille pas par ses capacités de calculs intensifs. De ce fait, il n'est pas raisonnable de faire, en Tcl, de grandes boucles de calcul sur tous les pixels d'une image, pour créer une nouvelle fonction de traitement d'image par exemple. C'est pour cette raison, et pour contourner ce problème, que Tcl fonctionne avec des "extensions".Une extension est une librairie dynamique qui apporte de nouvelles fonctions à Tcl. Les librairies dynamiques sont courament employées dans les programmes informatiques pour effectuer des tâches bien précises. Ces librairies sont des fichiers qui se reconnaissent habituellement par leur suffixe .dll sous Windows et .so sous Linux. Les librairies sont écrites en langage C ou C++, ce qui permet la vitesse d'exécution la plus rapide possible. Ainsi, il devient possible d'ajouter de nouvelles fonctions écrites en C à un script Tcl.
Prenons un exemple. Nous souhaitons créer une fonction somme qui retourne la somme de la valeur de tous les pixels de l'image supposée être dans le buffer 1 (buf1) de Audela. Cette fonction définie en Tcl pur, donnerait :
proc somme {} {
# --- retourne le nombre pixels en X ---
set naxis1 [lindex [buf1 getkwd NAXIS1] 1]
# --- retourne le nombre pixels en Y ---
set naxis2 [lindex [buf1 getkwd NAXIS2] 2]
set somme 0
# --- somme de tous les pixels ---
for {set i 1} {$i<=naxis1} {incr i} {
for {set j 1} {$j<=naxis2} {incr j} {
set somme [expr $somme+[buf1 getpix [list $i $j]]]
}
}
# --- retourne le resultat a l'interpreteur ---
return $somme
}
L'exécution d'une telle fonction Tcl prend énormément plus de temps que si elle était directement écrite en C. La même fonction, écrite en langage C, sous forme d'extension prends alors la syntaxe suivante :
int somme(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) {
float *p;
int naxis1,naxis2,numbuf;
double somme;
char s[50];
/* --- retourne l'adresse du pointeur image --- */
Tcl_Eval(interp,"buf1 pointer");
Tcl_GetInt(interp,p);
/* --- retourne le nombre pixels en X ---*/
Tcl_Eval(interp,"lindex [buf1 getkwd NAXIS1] 1");
Tcl_GetInt(interp,&naxis1);
/* --- retourne le nombre pixels en Y ---*/
Tcl_Eval(interp,"lindex [buf1 getkwd NAXIS2] 1");
Tcl_GetInt(interp,&naxis2);
/* --- somme de tous les pixels ---*/
somme=0;
for (i=0;i<naxis1;i++) {
for (j=0;j<naxis2;j++) {
somme=somme+(double)p[i*naxis2+j];
}
}
/* --- retourne le resultat a l'interpreteur ---*/
sprintf(s,"%lf",somme);
Tcl_AppendResult(interp,s);
return TCL_OK;
}
Les types ClientData et Tcl_Interp ainsi que TCL_OK sont définies dans tcl.h. Les fonctions Tcl_Eval, Tcl_GetInt et Tcl_AppendResult sont définies dans la librairie Tcl. Il faut charger ces fonctions dans la librairie d'extension. Dans les version supérieures à 8.1, on utilise le principe de stubs pour définir ces fonctions. L'extension devient alors indépendante de la version de Tcl utilisée. Le point d'entrée de la librairie contient le pointeur sur l'interpréteur Tcl (noté *interp en général). Parmi les fonctions Tcl accessibles, on trouvera la fonction qui crée la commande de syntaxe somme dans l'interpréteur Tcl de Audela et qui ira pointer sur la commande somme du langage C définie plus haut :
Tcl_CreateCommand(interp,"somme",somme,(ClientData)NULL,(Tcl_CmdDeleteProc
*)NULL);
Nous verrons plus loin tous les détails pour programmer une extension.
Les fonctions d'astronomie, apportées par audeLA, sont de véritables extensions. Il est important de connaître ces fonctions pour maîtriser l'écriture des scripts Tcl. Pour cela, nous avons regroupé la description des fonctions standard de Audela.
En programmant Audela, nous avons voulu donner la chance à un maximum de gens d'apprendre à programmer. Le langage Tcl permet de se faire la main et les extensions permettent de se plonger réellement dans la programmation en langage évolué. Nous avons écrit un manuel pour débuter en langage C afin de partir avec quelques bases saines. Enfin, nous livrons un canevas de sources C qui permet d'écrire facilement une extension. Il ne reste qu'à remplir les trous avec vos fonctions !
Un interpréteur Tcl peut charger une librairie d'extension en utilisant la fonction load de Tcl. Par exemple, pour charger la librairie libmc, on utilisera:
load libmc[info sharedlibextension]
La fonction[info sharedlibextension] ajoute l'extension adéquate au nom de fichier (.dll pour Windows ou .so pour Linux).