Audela |
![]() |
Les scripts Tcl/Tk permettent de personnaliser les applications astronomiques en fonction de l'usage que l'on compte en faire. Néanmoins, le langage Tcl est interprété et il est impossible de programmer des fonctions calculs puissants en Tcl. C'est pour cela que Audela ajoute des fonctions spécifiques à Tcl. Ces fonctions sont programmées en langage C ou C++ pour atteindre la vitesse maximale d'exécution. Néanmoins, Audela n'ajoute pas un ensemble complet de fonctions pour l'astronomie. Il en manque, c'est certain. Nous invitons les programmeurs expérimentés à participer au dévelopement de Audela en écrivant des fonctions C/C++. Ces fonctions peuvent être ajoutées à Audela sous la forme de librairies d'extension Tcl.
Ce chapitre expose les règles de compatibilité entre le C/C++ et Audela. Il y a deux façons de programmer : soit de créer une nouvelle librairie, soit de participer au développement de librairies existantes. Dans les deux cas, nous cherchons des partenaires. Cette page explique, en détails, comment programmer une librairie d'entension pour Audela. L'objet de ce texte est d'expliquer comment utiliser les fichiers de la librairie libxx afin de les transformer en une librairie personnalisée. Dans le principe, il suffit de télécharger le fichier libxx.zip qui contient tous les fichiers utiles et de le placer dans le dossier nommé dev qui accueille les fichiers sources de Audela. Ces fichiers contiennent tous les ingrédients de base d'une extension Tcl compilable indifféremment sous Windows (avec Visual C++) ou sous Linux (avec gcc). Dans un soucis de simplification, l'ensemble de la librairie est écrite en C et non en C++. L'extension .c des fichiers correpond donc à du C ANSI.
Les fichiers sources ont été nommés de façon à garder une grande clareté de lecture et pour garder une logique certaine. Il est nécessaire de garder cette architechture pour contruire une librairie de grande taille en ne s'y perdant pas. C'est pour cette raison que les conseils donnés ici sont décrits comme des consignes à respecter.
Une extension est une librairie externe qui est chargée à la demande par un interpréteur Tcl, pour augmenter le nombre de fonctions utilisables depuis cet interpréteur. Cela permet de répartir très facilement un travail de programmation entre plusieurs personnes, de manière complètement parallèle. La commande native Tcl
load
servira à charger une librairie dans l'interpréteur Tcl et enregistre automatiquement les nouvelles fonctions.
load libxx[info sharedlibextension]
La commande [info sharedlibextension] signifie à l'interpréteur Tcl d'ajouter, automatiquement, les lettres correspondant au suffixe .dll ou .so en fonction du système d'exploitation.
Un fichier d'extension est donc une librairie, c'est à dire une DLL sous Windows, ou une librairie partagée SO sous les systèmes UNIX / UNIX. Le schéma ci dessous précise le mécanisme adopté pour construire les librairies d'extension dans le cadre du projet Audela. Ces librairies sont, de fait, des extensions de n'importe quel interpréteur Tcl.
Le fichier d'extension doit contenir :
load(cf. fichier libxx.c, interface avec Tcl).
Le nom du point d'entrée (équivalent à la fonction main qui n'existe pas ici) doit s'appeller obligatoirement
Xx_Init
où Xx est le nom de la librairie, avec une majuscule obligatoire pour la première lettre (noter aussi le I majuscule dans Init). Le prototype de cette fonction est le suivant :
Sous Windows :
__declspec(dllexport) int __cdecl Xx_Init(Tcl_Interp *interp);
Sous Unix :
extern int Xx_Init(Tcl_Interp *interp);
Cette fonction recoit l'interpréteur Tcl qui l'a appelée (c'est donc l'interpréteur de Audela). C'est par cet argument qu'on enregistrera les nouvelles fonctions de la librairie. La fonction Xx_Init retourne un entier qui peut valoir entre autres TCL_OK ou TCL_ERROR. Cela donne des informations, à l'interpréteur appelant, du déroulement des opérations, pour éventuellement les répercuter à un niveau supérieur (arrêt de l'exécution d'un script par exemple).
Le rôle du point d'entrée est d'enregistrer, auprès de l'interpréteur, les fonctions que l'on souhaite ajouter à l'interpréteur, via notamment la fonction de la librairie Tcl :
Tcl_CreateCommand
. Le point d'entrée sert aussi à initialiser la librarie, en chargeant par exemple les librairies Tcl et Tk.
Nous considérons ici que les librairies Tcl et Tk utilisées sont de version supérieur ou égale à 8.3. A partir de la version Tcl/Tk 8.1 a été introduit la notion de stub. C'est un petit module qui permet d'apporter une compatibilité ascendante des fonctions Tcl et Tk à mesure que de nouvelles versions sortent. Ainsi, il n'est pas nécessaire de recompiler les librairies lorsque l'on change de version (excepté l'exécutable audela.exe qu'il faudra recompiler avec les nouvelles librairies). Le code C correspondant au chargement des stubs est codé dans la fonction Xx_Init :
if(Tcl_InitStubs(interp,"8.3",0)==NULL) { Tcl_SetResult(interp,"Tcl Stubs initialization failed in libxx.",TCL_VOLATILE); return TCL_ERROR; } if(Tk_InitStubs(interp,"8.3",0)==NULL) { Tcl_SetResult(interp,"Tk Stubs initialization failed in libxx.",TCL_VOLATILE); return TCL_ERROR; }
Sous Linux, nous considérons que Tcl/Tk 8.3 a été installé. Ainsi, le chargement des librairies dynamiques tcl.so et tk.so sont-ils effectués automatiquement sans ajouter de code source dans la librairie d'extension. La directive de chargement est codée au moment du link grâce aux options -ltclstub8.3 et -ltkstub8.3 de gcc. Pour s'assurer que Tcl/Tk est installé convenablement sous Linux, il faut trouver les fichiers suivants /usr/lib/tcl.so et /usr/lib/tk.so. En général, ces fichiers sont des liens pointant sur les fichiers tcl83.so et tk83.so. Enfin, s'assurer que les stubs de Tcl/Tk sont installé en trouvant les fichiers /user/lib/tclstub8.3.a et /user/lib/tkstub8.3.a. Noter que les fichiers .so sont des librairies dynamiques (équivalent aux DLL de Windows) alors que les fichiers .a sont des librairies statiques (équivalent aux LIB de Windows).
Sous Windows, il faut compiler les fichiers en définissant les symboles USE_TCL_STUBS et USE_TK_STUBS au niveau de la ligne de compilation (option /D). De plus, il faut lier les codes objets avec les librairies ..\..\common\lib_vc40\tclstub83.lib et ..\..\common\lib_vc40\tclstub83.lib.
Le code C de la librairie d'extension peux donc utiliser n'importe quelle des fonctions commençant par Tcl_ ou par Tk_ (cf. manuel d'utilisation disponible sur le net).
Ce sont les fonctions qui seront directement intégrées à l'interpréteur qui sollicitera la librairie. Elle doivent suivre un typage particulier, qui est le même que celui qui a été utilisé pour les librairies Tcl/Tk. L'exemple suivant montre comment l'extension enregistre la nouvelle fonction xx_julianday dans l'interpréteur Tcl :
Tcl_CreateCommand(interp,"xx_julianday",Cmd_xxtcl_julianday,(ClientData)NULL,(Tcl_CmdDeleteProc*)NULL);
Le premier arguement (interp) est donc l'interpréteur Tcl courant de Audela dans lequel la nouvelle fonction va être enregistrée. Le deuxième argument est le nom de la fonction tel qu'il sera connu par l'utilisateur de Audela. Le troisième arguement est le nom de la fonction C de la librairie d'extension qui va effectuer les calculs relatifs à ce que doit faire la nouvelle fonction Tcl "xx_julianday". Les deux derniers arguments sont généralement égaux au pointeur NULL mais peuvent être utilisés pour passer des paramètres particuliers (une structure de données par exemple). Noter le choix des noms de fonctions. Ils commencent tous par le nom de la librairie (xx_) afin d'assurer de ne pas détruire des fonctions d'autres librairies qui auraient le même nom.
L'interpréteur Tcl (variable interp) est une sctructure C qui contient un élément nomé result et qui va contenir une chaîne de caractères correspondant au résultat retourné à l'issu du calcul effectué par la fonction C (Cmd_xxtcl_julianday dans notre exemple).
Une nouvelle fonction est toujours de type int. Pour avoir une syntaxe cohérante, nous avons l'habitude de commencer le nom d'une nouvelle fonction par Cmd_ pour bien spécifier qu'il s'agit du "point d'entrée" d'une nouvelle fonction à enregistrer dans l'interpréteur Tcl. Ensuite, le nom continue par xxtcl_ pour signifier que le source C contiendra des fonctions des librairies Tcl ou Tk (ces fonctions commencent toutes par le préfixe Tcl_ ou Tk_). Enfin, on ajoute le nom de la fonction tel qu'il apparaîtra dans l'interpréteur Tcl. Ainsi, toutes les fonctions de "point d'entrée" de la librairie d'extension xx commenceront par Cmd_xxtcl_ et finiront par le nom de la fonction Tcl elle même. Dans le cas de la fonction Tcl xx_julianday, la fonction C associée est bien Cmd_xxtcl_julianday. Nous rappelons que cet usage n'est pas obligatoire mais permet de s'y retrouver lorsque plusieurs programmeurs travaillent sur une même extnesion.
Analysons le début du listing C de Cmd_xxtcl_julianday :
int Cmd_xxtcl_julianday(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
/****************************************************************************/
/* Retourne le jour julien a partir des la date en clair. */
/****************************************************************************/
/****************************************************************************/
{
int result,retour;
Tcl_DString dsptr;
char s[100];
double y=0.,m=0.,d=0.,hh=0.,mm=0.,ss=0.,jd=0.;
On remarque la présence du type Tcl_DString. Il s'agit d'une chaîne de caractères dynamique définie dans <tcl.h>. Ce type est très utile car il n'est pas utile de connaître la longueur de la chaîne par avance. Associé aux fonctions
Tcl_DStringInit
,
Tcl_DStringFree
,
Tcl_DStringAppend
et
Tcl_DStringResul
nous allons voir que le type Tcl_DString permet une gestion très simple de la chaîne de caratères qui sera retournée en sortie de la fonction.
Les premières lignes de C, concernant une fonction d'extension, vont être consacrées à la vérification du nombre d'arguments attendus par la fonction :
if(argc<4) {
sprintf(s,"Usage: %s year month day ?hour min sec?", argv[0]);
Tcl_SetResult(interp,s,TCL_VOLATILE);
result = TCL_ERROR;
Dans cet exemple, la fonction admet trois mots obligatoires (year month day) et trois autres facultatifs (la syntaxe entre les deux ? est une règle d'usage de Tcl pour désigner les arguments facultatifs). La fonction Cmd_xxtcl_julianday reçoit les arguements Tcl sous la forme du pointeur de chaînes *argv[]. L'entier argc contient le nombre de chaînes contenues dans *argv[]. Le nom de la fonction elle même (xx_julianday) est le premier argument et les trois autres suivant montrent que argc doit être au moins égal à 4 pour vérifier qu'il y ait 3 arguments après le nom de la fonction. Si ce n'est pas le cas alors on retourne le code TCL_ERROR et on stocke l'aide de la fonction en tant que chaîne de retour. La chaîne de retour de la fonction est remplie par la fonction Tcl_SetResult.
La suite du listing C montre le traitement de la fonction dans le cas où au moins trois arguements ont été trouvés. Il s'agit maintenant de transformer ces arguments en valeurs numériques pour le langage C. Pour cela, on se sert des fonctions de type Tcl_GetDouble, Tcl_GetInt, etc.
} else {
/* --- decode les parametres obligatoires ---*/
retour = Tcl_GetDouble(interp,argv[1],&y);
if(retour!=TCL_OK) return retour;
retour = Tcl_GetDouble(interp,argv[2],&m);
if(retour!=TCL_OK) return retour;
retour = Tcl_GetDouble(interp,argv[3],&d);
if(retour!=TCL_OK) return retour;
/* --- decode les parametres facultatifs ---*/
if (argc>=5) {
retour = Tcl_GetDouble(interp,argv[4],&hh);
if(retour!=TCL_OK) return retour;
}
if (argc>=6) {
retour = Tcl_GetDouble(interp,argv[5],&mm);
if(retour!=TCL_OK) return retour;
}
if (argc>=7) {
retour = Tcl_GetDouble(interp,argv[6],&ss);
if(retour!=TCL_OK) return retour;
}
Il devient désormais possible d'effectuer les calculs propres à la fonction C. Ces calculs ne font pas intervenir de fonctions Tcl. Il est donc préférable d'écrire les fonctions qui ne contiennent pas de Tcl dans un fichier à part. Le but est de concentrer, dans certains fichiers, du C mélangé avec des fonctions Tcl et dans d'autres des fonctions de C pur. On comprend mieux cette démarche si on prend le problème à l'envers. En général, on part de fonctions C pur qui effectuent du calcul. On a envie alors de construire une librairie d'extension Tcl en "enrobant" ces fonctions par les fonctions qui font le lien entre C et Tcl. Ainsi, on peut distinguer clairement les problèmes venant de l'intéraction C/Tcl et les problèmes propres aux calculs en C pur. Dans notre exmple, le calcul du jour julien est effectué dans une fonction spécifique, écrite en C pur. Dans la fonction Cmd_xxtcl_julianday, on se contente d'appeler cette fonction :
/* --- calcule le jour julien ---*/
xx_date2jd(y,m,d,hh,mm,ss,&jd);
La valeur du jour julien doit maintenant être transformée dans l'autre sens : d'une variable numérique C vers une chaîne de caractères. C'est à ce moment là que l'on utilise le type Tcl_DString :
/* --- allocation memoire de la dynamic string ---*/
Tcl_DStringInit(&dsptr);
/* --- met en forme le resultat dans une chaine de caracteres classique ---*/
sprintf(s,"%lf",jd);
/* --- on ajoute cette chaine a la dynamic string ---*/
Tcl_DStringAppend(&dsptr,s,-1);
/* --- a la fin, on envoie le contenu de la dynamic string dans */
/* --- le Result qui sera retourne a l'utilisateur. */
Tcl_DStringResult(interp,&dsptr);
/* --- desaloue la dynamic string. */
Tcl_DStringFree(&dsptr);
Il reste encore à spécifier que la fonction a été effectuée sans problème avec la variable TCL_OK :
/* --- retourne le code de succes a
l'interpreteur Tcl */
result = TCL_OK;
}
Enfin, on retourne le code erreur pour sortir de la fonction :
return result;
}
L'architechture des fonctions d'extension est toujours calquée sur ce qui vient d'être présenté. La librairie xx ne sert qu'à montrer le canevas de ce qu'il faut écrire. A vous de la modifier pour créer votre propre librairie d'extension Tcl pour Audela.
Nous allons étudier la librairie nommée xx. Elle peut se télécharger. Une fois décompressée, la structure des dossiers est la suivante :
Il n'est pas utile d'avoir compris en détail les explications du paragraphe précédent pour continuer à lire ce texte. En effet, nous allons nous contenter de comprendre ce qu'il faut changer dans les fichiers de la librairie xx pour ajouter de nouvelles fonctions.
Pour créer une nouvelle librairie, il suffit de changer tous les xx en le nom de la librairie que l'on souhaite. Néanmoins, l'usage veut que, sous Unix, les librairies commencent par les trois lettres lib. Bien que cette façon de faire ne soit nullement obligatoire, nous reconseillons de l'utiliser afin de garder une cohérence. Pour créer la librairie libmagic, il suffit de prendre tous les fichiers de la libxx et de remplacer xx par magic.
Sous windows, il faut aussi recréer un nouveau projet si l'on utilise le compilateur Visual C++ 4.0. Dans la cas du projet libxx, on procèdera ainsi, dans l'ordre suivant pour créer le fichier projet libxx.mdp (et libxx.mak) :
Sous Linux, il suffit d'éditer le fichier Makefile et de remplacer xx par le nom de la librairie.
L'architecture générale des fichiers de libxx est organisée pour ajouter facilement une nouvelle fonction. Si la fonction xx_julianday n'était pas encore programmée, voici comment il faudrait procéder:
Tcl_CreateCommand(interp,"xx_julianday",Cmd_xxtcl_julianday,(ClientData)NULL,(Tcl_CmdDeleteProc
*)NULL);
int Cmd_xxtcl_julianday(ClientData clientData, Tcl_Interp *interp,
int argc, char *argv[])
{
...corps de la fonction...
}
int Cmd_xxtcl_julianday(ClientData clientData, Tcl_Interp
*interp, int argc, char *argv[]);
void xx_date2jd(double annee, double mois, double jour, double heure, double minute, double seconde, double *jj){ ...corps de la fonction...}
void xx_date2jd(double annee, double mois, double jour, double heure, double minute, double seconde, double *jj);
Deux fonctions ont été implémentées dans libxx de façon à montrer deux exemples de programmation. Le premier exemple concerne une routine de calcul, le deuxième concerne la manipulation du pointeur d'image de Audela.
La fonction xx_julianday est jointe à l'interpréteur Tcl dans le fichier libxx.c à la ligne suivante :
Tcl_CreateCommand(interp,"xx_julianday",Cmd_xxtcl_julianday,(ClientData)NULL,(Tcl_CmdDeleteProc*)NULL);
Le prototype de cette fonction se trouve dans le fichier libxx.h. Pour changer le nom de la fonction, vu de l'utilisateur de l'interpréteur, il suffirait de changer "xx_julianday" en une autre chaîne de caratères. La ligne ci-dessus signifie à l'interpréteur d'aller à la fonction Cmd_xxtcl_julianday, lorsqu'il voit le mot xx_julianday comme premier argument de la ligne Tcl à évaluer.
La fonction Cmd_xxtcl_julianday est écrite dans le fichier xxtcl_1.c et son prototype dans xxtcl.h :
int Cmd_xxtcl_julianday(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
/****************************************************************************/
/* Retourne le jour julien a partir des la date en clair. */
/****************************************************************************/
/****************************************************************************/
{
int result,retour;
Tcl_DString dsptr;
char s[100];
double y=0.,m=0.,d=0.,hh=0.,mm=0.,ss=0.,jd=0.;
if(argc<4) {
sprintf(s,"Usage: %s year month day ?hour min sec?", argv[0]);
Tcl_SetResult(interp,s,TCL_VOLATILE);
result = TCL_ERROR;
} else {
/* --- decode les parametres obligatoires ---*/
retour = Tcl_GetDouble(interp,argv[1],&y);
if(retour!=TCL_OK) return retour;
retour = Tcl_GetDouble(interp,argv[2],&m);
if(retour!=TCL_OK) return retour;
retour = Tcl_GetDouble(interp,argv[3],&d);
if(retour!=TCL_OK) return retour;
/* --- decode les parametres facultatifs ---*/
if (argc>=5) {
retour = Tcl_GetDouble(interp,argv[4],&hh);
if(retour!=TCL_OK) return retour;
}
if (argc>=6) {
retour = Tcl_GetDouble(interp,argv[5],&mm);
if(retour!=TCL_OK) return retour;
}
if (argc>=7) {
retour = Tcl_GetDouble(interp,argv[6],&ss);
if(retour!=TCL_OK) return retour;
}
/* --- le type DString (dynamic string) est une fonction de */
/* --- l'interpreteur Tcl. Elle est tres utile pour remplir */
/* --- une chaine de caracteres dont on ne connait pas longueur */
/* --- a l'avance. On s'en sert ici pour stocker le resultat */
/* --- qui sera retourne. */
Tcl_DStringInit(&dsptr);
/* --- calcule le jour julien ---*/
xx_date2jd(y,m,d,hh,mm,ss,&jd);
/* --- met en forme le resultat dans une chaine de caracteres ---*/
sprintf(s,"%lf",jd);
/* --- on ajoute cette chaine a la dynamic string ---*/
Tcl_DStringAppend(&dsptr,s,-1);
/* --- a la fin, on envoie le contenu de la dynamic string dans */
/* --- le Result qui sera retourne a l'utilisateur. */
Tcl_DStringResult(interp,&dsptr);
/* --- desaloue la dynamic string. */
Tcl_DStringFree(&dsptr);
/* --- retourne le code de succes a l'interpreteur Tcl */
result = TCL_OK;
}
return result;
}
A un moment donnée, le calcul par lui même est appelé par la fonction xx_date2jd écrite dans le fichier xx_1.c (et son prototype dans xx.h). La fonction xx_date2jd ne contient aucune fonction venant du Tcl/Tk (c'est à dire ne nécessitant les includes tcl.h et tk.h) :
void xx_date2jd(double annee, double mois, double jour, double heure, double minute, double seconde, double *jj)
/***************************************************************************/
/* Donne le jour juliene correspondant a la date */
/***************************************************************************/
/***************************************************************************/
{
double a,m,j,aa,bb,jd;
a=annee;
m=mois;
j=jour+((((seconde/60.)+minute)/60.)+heure)/24.;
if (m<=2) {
a=a-1;
m=m+12;
}
aa=floor(a/100);
bb=2-aa+floor(aa/4);
jd=floor(365.25*(a+4716))+floor(30.6001*(m+1))+j+bb-1524.5;
*jj=jd;
}
En conclusion, la fonction xx_julianday est écrite selon trois niveaux hiérarchiques :
De cette façon, il devient facile de transformer une librarie C standard en une librairie d'extension Tcl. Il suffit d'écrire les fonctions d'interfaçage C/Tcl en créeant des fichiers de type xxtcl_*.c (ou xx sera remplacé par le nom de la librairie). Enfin, le fichier de type libxx.c contiendra les appels accessibles depuis l'interpréteur Tcl.
Enfin, dernière règle, les fonctions écrites dans un fichier donnée ont leur prototype dans le fichier .h qui a le même nom (sans les indices). Par exemple, une fonction écrite dans un hypothétique fichier xx_3.c aurait son prototype dans xx.h.
La fonction xx_infoimage est jointe à l'interpréteur Tcl dans le fichier libxx.c à la ligne suivante :
Tcl_CreateCommand(interp,"xx_infoimage",Cmd_xxtcl_infoimage,(ClientData)NULL,(Tcl_CmdDeleteProc*)NULL);
Le prototype de cette fonction se trouve dans le fichier libxx.h. La ligne ci-dessus signifie à l'interpréteur d'aller à la fonction Cmd_xxtcl_infoimage, lorsqu'il voit le mot xx_infoimage comme premier argument de la ligne Tcl à évaluer.
La fonction Cmd_xxtcl_image est écrite dans le fichier xxtcl_1.c et son prototype dans xxtcl.h :
int Cmd_xxtcl_infoimage(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
/****************************************************************************/
/* Retourne des infos sur l'image presente dans un buffer de Audela */
/****************************************************************************/
/****************************************************************************/
{
int result,retour;
Tcl_DString dsptr;
char s[100];
xx_image image;
int numbuf;
if(argc<2) {
sprintf(s,"Usage: %s numbuf", argv[0]);
Tcl_SetResult(interp,s,TCL_VOLATILE);
result = TCL_ERROR;
} else {
result = TCL_OK;
/* --- decode le parametre obligatoire ---*/
retour = Tcl_GetInt(interp,argv[1],&numbuf);
if(retour!=TCL_OK) return retour;
/*--- initialise la dynamic string ---*/
Tcl_DStringInit(&dsptr);
/* --- recherche les infos ---*/
result=xxtcl_getinfoimage(interp,numbuf,&image);
/* --- met en forme le resultat dans une chaine de caracteres ---*/
sprintf(s,"%p %ld %ld %s",image.ptr_audela,image.naxis1,image.naxis2,image.dateobs);
/* --- on ajoute cette chaîne à la dynamic string ---*/
Tcl_DStringAppend(&dsptr,s,-1);
/* --- a la fin, on envoie le contenu de la dynamic string dans */
/* --- le Result qui sera retourne a l'utilisateur. */
Tcl_DStringResult(interp,&dsptr);
/* --- desaloue la dynamic string. */
Tcl_DStringFree(&dsptr);
}
return result;
}
A un moment donnée, le calcul par lui même est appelé par la fonction xxtcl_getinfoimage. Contrairement à xx_date2jd, xxtcl_getinfoimage est écrite dans xxtcl_1.c (et son prototype dans xxtcl.h). En effet, xxtcl_getinfoimage a le pointeur de l'interpréteur Tcl comme argument (*interp). Ainsi xxtcl n'étant pas une fonction écrite en C ANSI pur, elle apparaît dans le fichier xxtcl_1.c. Dans ce fichier on voit donc deux types de fonctions, dont les préfixes sont :
Cmd_xxtcl_ : pour les fonctions appelées directement par l'interpréteur Tcl à partir du fichier libxx.c.
xxtcl_ : pour les fonctions mélangeant C et Tcl mais n'étant pas appelées par libxx.c.
Le pointeur d'un buffer image Audela ne doit pas être manipilé n'importe comment. L'adresse
p
(toujours de type *float) du pointeur de l'image en buffer 1 est retourné par:
Tcl_Eval(interp,"buf1 pointer");
Tcl_GetInt(interp,interp->result,&ptr);
p=(float*)ptr;
Il ne faut surtout pas faire un free sur le pointeur de l'image. En effet, le free effectué dans votre librairie ne pourra pas nécessairement être exécuté si votre librairie et Audela sont situés dans des segments mémoires différents (risque de blocage général dans Windows et d'un fichier core sous Linux). Si l'on veut effacer l'image du buffer 1, alors on utilisera :
Tcl_Eval(interp,"::buf::delete 1");
Pour créer un nouveau buffer (de dimension 768 512 pixels), on utlisera :
Tcl_Eval(interp,"::buf::create 1");
Tcl_Eval(interp,"buf1 format 768 512");
La fonction xxtcl_getinfoimage retourne les informations de l'image dans une structure interne à la librarie xx. Ce cette façon, on peut effectuer des traitements d'images, sans passer par Tcl, à l'intérieur des fichiers de type xx_*.c.