INTERFACER DES ROUTINES EXTERNES AVEC MUSTIG
tableau des matières
5-1. Introduction
5-1-1. Le principe
5-2. Définir l'interface dans MUSTIG
5-2-1. Le module Extern
5-2-2. Définir la fonction des bornes sur le module Extern
Entrer le texte de l'interface
5-2-3. Code d'interface ajouter à la DLL
Pointeurs utilisés pour se référer au tableau de données
Se référer aux données dans le code C externe
5-2-4. Exemple de routine externe interfacée en C et Fortran
5-3-1. Macintosh 680xx
5-3-2. Power Macintosh
5-4-1. Le processus de mémoire partagée
5-6. PC + AU32
Créer la routine externe .tms pour la carte AU32
5. Interfacer des routines externes avec MUSTIG
Les routines externes peuvent être appelées à partir d'un graphe MUSTIG :
Les données d'entrée (par exemple signaux, paramètres numériques, chaînes, description de variable) sont définies dans MUSTIG et sont passées à la routine externe. Cette dernière traite les données incidentes et produit des données de sortie qui sont rendues à MUSTIG pour traitement ultérieur ou affichage.
Les données de sortie n'ont pas forcément la même structure que les données d'entrée. Par exemple, vous pouvez définir un signal 2D, plus un vecteur de paramètres, plus une chaîne comme paramètres d'entrée, et produire seulement un scalaire sur la sortie.
Cela permet d'utiliser des routines pernonnelles existantes sans devoir les récrire complètement en langage MUSTIG. Certains algorithmes sont écrits dans un langage procédural comme C plus facilement que dans MUSTIG. Dans ce cas, ce peut être une meilleure idée de créer et interfacer une routine externe, que de construire un graphe MUSTIG qui fait le même travail.
5-1-2. Contraintes sur le code externe
Sur quelques machines (par exemple Macintosh 680xx ou Sun/OS), le code doit avoir seulement un point d'entrée : vous ne pouvez pas utiliser des DLLs d'entrée multiple .
Bien sûr, le code a besoin d'être modifié légèrementpour autoriser la communication d'entrée et de sortie avec MUSTIG (voyez Définir l'interface dans le code externe).
5-2. Définir l'interface dans MUSTIG
Le module de l'interface externe est disponible dans la section <-> de la bibliothèque:
|
permet de connecter un programme C avec MUSTIG |
|
permet de connecter un programme Fortran avec MUSTIG |
Le module a initialement 8 bornes, comptées de 1 à 8 comme les aiguilles d'une montre:
Vous pouvez ajouter ou enlever des bornes si nécessaire (voyez Créer une borne et Effacer une borne): les bornes sont renumérotées comme les aiguilles d'une montre, en commençant à la borne la plus basse sur le bord gauche du module.
La structure des données d'entrée et de sortie sera décrite comme un texte entré dans la face avant du module. Vous pouvez redimentionner le module si nécessaire. Chaque borne peut être utilisée comme une borne d'entrée ou comme une borne de sortie, selon comme c'est indiqué dans le texte.
5-2-2. Définir la fonction des bornes dans le module Extern
Entrer le texte de l'interface
Vous choisissez maintenant le type et structure des données sur chaque borne.
Si ce nom est My_Subprog par exemple, MUSTIG cherchera une routine externe nommée My_Subprog, My_Subprog.sub ou My_Subprog.dll dans le répertoire courant en premier, et puis dans les répertoires spécifiés par l'utilisateur dans Edition / Options / Chemins et dans les variables d'environnement.
Le nom peut être aussi une entrée dans une DLL d'entrée multiple (si disponible sur votre machine). Par exemple, le nom
My_dll@My_Routine
fait référence à une routine nommée My_Routine dans la DLL nommée My_dll.dll.
<numéro de borne><direction><type de donnée>[<variable(s) associée(s)>]
Champ |
Valeurs possibles |
Fonction |
<numéro de la borne> |
1 à nombre de bornes total |
Numéro de la borne (voir Le module Extern) |
<direction> |
+ : borne de sortie - : borne d'entrée |
Définit la direction de la borne (entrée ou sortie) |
<ype des données> |
I1,I2, I4 pour les nombres entiers, R4, R8 pour les réels, C8, C16 pour les complexes, W pour un plan graphique S pour une chaîne X type indifférent (voir ci-dessous) |
Définit le type des données sur la borne. Voir les exemples livrés avec Mustig pour une démonstration de comment un plan graphique doit être traité. |
<variable(s) associée(s) > |
Si les données ne sont pas scalaires, le nom de la(des) variable(s) est spécifié après un signe ' / ' comme d'habitude. |
Le type X " indifférent ":
Si la routine externe produit un signal de sortie (c.-à-d. un vecteur, une matrice, un signal 3D,…), ce signal doit être porté par au moins une variable. Si le signal de sortie a exactement les même attributs qu'un signal d'entrée, le même nom de variable peut être utilisé (voir les Attributs d'une variable).
Cependant, si les attributs d'un signal de sortie sont différents de ceux d'un des signaux d'entrée, une description de variable appropriée doit être entrée sur une borne d'entrée du module Extern. La ligne associée sur la face avant du module est entrée avec un type égal à X, signifiant que seulement les attributs de la variable sont utilisés, et non les données qu'il porte s'il y en a.
Dans l'exemple précité, la DLL externe est appelée avec deux scalaires comme données d'entrée, et retourne un vecteur. L'utilisateur doit dire ce que sont les caractéristiques du vecteur produit à MUSTIG, en ajoutant une borne d'entrée (borne #3 ici) suivi à une description variable avec les attributs appropriés. Cette description peut être ramassée d'un signal existant: seulement les attributs seront utilisés, pas les données elles-mêmes.
S'il vous plaît notez qu'une " borne X " ne doit pas être référencée dans le code DLL externe, elle est utilisée par Mustig seulement.
Exemple
Si on suppose que le scalaire de la sortie est un nombre réel, le texte de l'interface pour l'exemple présenté dans le paragraphe 1 pourrait être :
Autres exemples de lignes d'interface valides
1-C8/x/y |
La borne #1 est une borne d'entrée, portant des données complexes de simple précision distribuées comme un 2D signal selon les variables x et y. |
3-X/u |
La borne #3 est une borne d'entrée, portant la description d'une variable nommée u. Cette variable sera utilisée pour construire un signal de sortie. |
6+S |
La borne #6 est une borne de sortie qui rend une chaîne du caractère |
1-W |
La borne #1 est une borne d'entrée portant un plan graphique |
4+I2/t |
La borne #4 est une borne de sortie qui rend un vecteur de nombres entiers de 2 octets selon une variable nommée t. |
Suivant la description des bornes dans le texte de l'interface, l'utilisateur peut entrer une ou les deux des lettres suivantes :
IX |
Habituellement, si la mémoire disponible est insuffisante pour traiter un signal, la routine externe peut être appelée plusieurs fois par Mustig. Si le drapeau X est présent dans le texte de l'interface, ce processus est mis hors fonction. Utilisez ce drapeau quand connecter MUSTIG avec les routine d'acquisition de données. |
5-2-3. Code d'interface à ajouter à la DLL
Le processus d'interfaçage d'une routine externe avec MUSTIG a été décrit ci-dessus du point de vue de MUSTIG.
Dans cette section, nous décrivons comment l'interface est écrite du point de vue du code externe : le code externe doit savoir où sont les données d'entrée et où entreposer les résultats de la sortie. Cette section exige que le lecteur soit familier avec les notions de pointeur et adresse mémoire.
Bien sûr, le nom des pointeurs et variables peut être différent de ceux présentés dans les sections suivantes. Vous êtes libre de choisir des noms plus explicites, ou plus compacts si vous souhaitez.
Les pointeurs utilisés pour faire référence au tableau des données
Quand on entre dans la routine externe, le stack contient trois pointeurs :
Nom |
Pointe sur |
Fonction |
t |
La tableau des données de Mustig |
Première adresse du tableau des données |
p |
Tableau des paramètres (voir ci-dessous) |
Fait référence aux bornes |
r |
Une chaîne de 80 caractères |
Message d'erreur à retourner |
La tableau de paramètres est constitué de nombres entiers 32 bits.
Langage C : La tableau des paramètres est déclaré comme une structure p de nombres entiers longs, et les éléments décrits ci-dessous sont les composants de la structure. (voir l'exemple).
Langage Fortran : La tableau de paramètres p et ses composants (c.-à-d. les variables listées ci-dessous) est déclaré comme variables de integer*4. Pour chaque borne, l'utilisateur appelle un sous-programme spécifique nommé mstg#v où # remplace le nombre de variables sur la borne (voir l'exemple)
Nom de Var. |
Fonction |
i |
Index réservé (initialisé à 2) |
nb_pins |
Nombre de bornes connectées- permet de vérifier que le nombre de bornes connectées est correct - Si le nb_pins est trouvé égal à 0, cela veut dire que l'option " I " a été entrée dans le texte de l'interface du module Extern et la routine externe est appelée à nouveau quand les calculs sont finis (voir les modes d'appel facultatifs). Les bornes déclarées comme ayant le type X dans le module Extern ne sont pas incluses dans ce compte. |
Nom de Var. |
Fonction |
nvar # |
Nombre de variables (ou dimensions) portées par la borne :
|
d # |
Place dans la tableau des données pointée par le pointeur t. |
Nom de Var. |
Fonction |
in# |
Un incrément entre valeurs consécutives selon la variable |
n # |
Nombre d'échantillons selon cette dimension |
Exemple de déclaration de variable potentielle :
nvar0, d0, | La borne #0 porte un scalaire. Donc, nvar0 sera mis à 0 (aucune variable) par Mustig en appelant la routine externe. Nous recommandons que cela soit vérifié dans votre code. |
nvar1, d1, in1, n1, | La borne #1 porte un vecteur (c.-à-d. le signal a une variable là). Donc les nvar1 seront mis à 1 par Mustig. |
nvar2, d2, in2, n2, in21, n21, | La borne #2 porte une matrice (c.-à-d. le signal a deux variables là). Donc, les nvar2 seront mis à 2. |
nvar3, d3, in3, n3, in31, n31, n32, in32,, | La borne #3 porte un signal 3D (c.-à-d. le signal a trois variables là). Donc, les nvar2 seront mis à 3. |
Note : Dans ces déclarations de variables, les bornes sont comptées de 0 à Npins -1. Vous pouvez changer ceci et comptez la borne de 1 à Npins si vous voulez. Juste changez les noms de variables en conséquence. Les noms des variables ne sont pas utilisés comme mots-clé, donc vous pouvez leur donner les noms que vous voulez.
Faire référence aux données dans le code C externe
Le pointeur t peut être vu comme l'adresse du premier élément d'un grand segment de mémoire : le tableau de données Mustig .
Les données portées par chaque borne (soit entrée soit sortie) sont accédées en utilisant les variables précédemment déclarées d# (voir Le tableau des paramètres) qui donnent le décalage dans le tableau des données pour chaque borne :
Cas 1 : la borne porte un scalaire
valeur = * (t + p->d0);
où "valeur" est une variable du même type que celle déclarée pour la borne dans le texte de l'interface sur le module Extern Mustig. Autrement, les conversions automatiques seront faites par votre ordinateur et le résultat peut ne pas être bien portable aux autres machines.
* (t + p->d0) = valeur;
* (t + p->d0) = 0.5213;
Note : Vous pouvez utiliser aussi des variables intermédiaires et des pointeurs pour faire référence à la borne, si vous trouvez cela plus lisible :
int *pin_0; / * déclare un pointeur intermédiaire * /
pin_0 = (t + p->d0); / * cela réfère à la borne #0 * /
valeur = *pin_0; / * lu si c'est une borne d'entrée * /
pin_0 = valeur; / * ou écrit si c'est une borne de sortie * /
Cas 2: la borne porte un vecteur
Supposez que la borne #0 porte un vecteur. Un segment de mémoire est donné à ce vecteur, qui commence à l'adresse
t + p->d0
Cette adresse correspond au premier élément du vecteur. Pour lire ou écrire les autres éléments du vecteur, utilisez l'incrément de variable précédemment déclaré in# qui donne le nombre d'octets entre deux éléments consécutifs du vecteur:
t + p->d0 |
Adresse du premier élément = vector[0] |
t + p->d0 + in0 |
Adresse du deuxième élément = vector[1] |
t + p->d0 + n*in0 |
Adresse de l'élément énième = vector[n] |
Exemples:
val = * (t + p->d0 + 2*in0) | Une variable précédemment déclarée nommée val est mise à la valeur du troisième élément du vecteur sur la borne d'entrée 0. |
* (t + p->d0 + 2*in0) = val | Le troisième élément du vecteur sur la borne de sortie 0 est mise à la valeur de la variable val . |
vecteur = t+p->d0 | Le pointeur 1D vecteur est associé à la borne 0 |
Cas 3: la borne porte une matrice
Suivant le même principe, si la borne porte une matrice, vous pouvez faire référence à tout élément en utilisant les incréments de variables sur les deux dimensions. Utilisez cette adresse pour lire ou écrire les données comme d'habitude.
t + p->d0 + i*in0 + j*in1 | Adresse de l'élément localisé à la ième place selon la première variable et à la jème place selon la deuxième variable. |
La même technique est utilisée si le signal sur la borne a plus de deux dimensions.
5-2-4. Exemple de routine externe interfacée en C et Fortran
L'exemple suivant de traitement de matrice externe est fourni avec Mustig :
Voici la matrice d'entrée 3x2 sur borne 1, entrée en cliquant deux fois sur la macro Matrice/li/co :
et voici la matrice 3x2 de sortie calculée passée sur la borne 6 :
Elle a été calculée en utilisant l'algorithme suivant écrit dans la routine externe :
Les résultats suivants sont calculés par la routine externe et sont passés aux bornes de la sortie:
Borne 4 | Deuxième colonne de la matrice de sortie calculée |
Borne 5 | Deuxième ligne de la matrice de sortie calculée |
Borne 6 | Matrice de sortie calculée |
Borne 7 | Somme des éléments de la matrice d'entrée |
Le code C de la routine externe est donné ci-dessous : les commentaires expliquent comment les paramètres sont retrouvés réellement.
/* Example of external << C >> routine */
/*
IMPORTANT NOTE
In this external routine, the pins are referred to using variables which contain a "pin number". These pin numbers range from 0 to the number of CONNECTED pins minus 1.
In Mustig, the Extern module numbers the pins from 1 to the number of EXISTING pins (either connected or not) and some pins are not connected.
Therefore, pin N in this code does NOT correspond to pin N as it is numbered on the interface text of the Extern Mustig module
*/
void __export matrice(t,p,r)
char *t; /* Pointer to the Mustig data table (array) */
char *r; /* String to return potential error messages */
struct {long /* Parameter table */
i, /*index initialized to "2" */
nb_pins, /*number of pins used*/
/*pin 0, scalar input, integer on 4 octets*/
nvar0, /* number of variables support of signal on
the pin (should be 0) */
d0, /* offset in array t */
/*pin 1,matrix input, real*/
nvar1, /* number of variables support of signal on
the pin (should be 2) */
d1, /* offset in array t */
in1, /* increment on the first dimension */
n1, /* number of values */
in12, /* increment on the second dimension */
n12, /* number of values */
/*pin 2,vector output, real*/
nvar2, /* number of variables support of signal on
the pin (should be 1) */
d2, /* offset in array t */
in2, /* increment */
n2, /* number of values */
/*pin 3,vector output, real*/
nvar3, /* number of variables support of signal on
the pin (should be 1) */
d3, /* offset in array t */
in3, /* increment */
n3, /* number of values */
/*pin 4, matrix output, real*/
nvar4, /* number of variables support of signal on
the pin (should be 2)*/
d4, /* offset in array t */
in4, /* increment on the first dimension */
n4, /* number of values */
in42, /* increment on the first dimension */
n42, /* number of values */
/*pin 5, scalar output, real*/
nvar5, /* number of variables support of signal on
the pin (should be 0) */
d5; /* offset in array t */
} *p;
/* End of the description of the pointer to the parameter list */
/* Begin the main program */
{
static float value=0.5;
int err,i,j;
float *a,*b,*a0,*b0,*v1,*v2;
long val0;
float fval0,*afval5,s;
long n1,n2,inc1,inc12,incv1,incv2,inc4,inc42;
/* Check the input data and declare intermediate variables */
if(p->nb_pins != 6) {strncpy(r,"wrong number of connected
pins,80);return;}
/*pin 0*/
if(p->nvar0 != 0){strncpy(r,"Connected Pin 0 not a scalar",80);return;}
val0=*((long*)(t+p->d0));
fval0=val0;
/*pin 1*/
if(p->nvar1 != 2){strncpy(r," Connected Pin 1 not a matrix",80);return;}
a0=(float*)(t+p->d1); /*address of input matrix*/
n1 = p->n1; /* number of matrix points along 1st dimension */
n2 = p->n12; /* number of matrix points along 2nd dimension */
inc1 = p->in1; /* increment of matrix points along 1st dim */
inc12 = p->in12; /* increment of matrix points along 2nd dim */
/*pin 2*/
if(p->nvar2 != 1){strncpy(r," Connected Pin 2 not a vector",80);return;}
v1=(float*)(t+p->d2); /* address of first vector output */
if(p->n2 != n1){strncpy(r,"error vector-matrix",80);return;}
incv1 = p->in2; /* increment of vector points */
/*pin 3*/
if(p->nvar3 != 1){strncpy(r," Connected Pin 3 not a vector",80);return;}
v2=(float*)(t+p->d3); /* address of second vector output */
if(p->n3 != n2){strncpy(r,"error vector-matrix",80);return;}
incv2 = p->in3; /* increment of vector points */
/*pin 4*/
if(p->nvar4 != 2){strncpy(r," Connected Pin 4 not a matrix",80);return;}
b0=(float*)(t+p->d4); /* address of output matrix */
inc4 = p->in4; /* increment of matrix points along 1st dim */
inc42 = p->in42; /* increment of matrix points along 2nd dim */
/*pin 5*/
if(p->nvar5 != 0){strncpy(r," Connected pin 5 not a scalar",80);return;}
afval5=(float*)(t+p->d5);
s=0;
/*calculation of the output matrix from the input matrix */
for(i=0;i<n1;i++){
a=a0;
b=b0;
for(j=0;j<n2;j++){
*b= *a + fval0 + value;
s += *a;
a += inc12;
b += inc42;
}
value += fval0;
a0 += inc1;
b0 += inc4;
}
*afval5=s; /*result on pin5 is the sum of the terms of the input matrix*/
/*calculation of first vector = second column of matrix b*/
b0=(float*)(t+p->d4);/*address of output matrix*/
b=b0 + inc42;
for(i=0;i<n1;i++){
*v1 = *b;
v1 += incv1;
b += inc4;
}
/*calculation of second vector = second line of matrix b*/
b=b0 + inc4;
for(i=0;i<n2;i++){
*v2 = *b;
v2 += incv2;
b += inc42;
}
}
Le code FORTRAN pour la même routine externe est donné ci-dessous :
c example of external routine FORTRAN
program MATRIX(t,p,r)
c systematic declarations for Mustig interface
integer*4 p
integer*1 t(0:1)
integer*1 r(80)
c declarations required for every declared pin
c - an address
c - for each support variable :
c - an increment
c - a number of values
c
integer*4 ad0,ad1,ad2,ad3,ad4,ad5,inc1,nv1,inc12,nv12
integer*4 inc2,nv2,inc3,nv3,inc4,nv4,inc42,nv42,ierr
external SPMATRIX
integer SPMATRIX
c a call to 'mstg0v' or 'mstg1v' or 'mstg2v'
c for each pin declared in the MUSTIG module
c pin 0
call mstg0v(p,ad0,ierr)
if(ierr .NE. 0) GOTO 100
c pin 1
call mstg2v(p,ad1,inc1,nv1,inc12,nv12,ierr)
if(ierr .NE. 0) GOTO 100
c pin 2
call mstg1v(p,ad2,inc2,nv2,ierr)
if(ierr .NE. 0) GOTO 100
c pin 3
call mstg1v(p,ad3,inc3,nv3,ierr)
if(ierr .NE. 0) GOTO 100
c pin 4
call mstg2v(p,ad4,inc4,nv4,inc42,nv42,ierr)
if(ierr .NE. 0) GOTO 100
c pin 5
call mstg0v(p,ad5,ierr)
c test of parameter coherency
100 if (ierr .NE. 0)then
call mstger(r,'Incoherent call')
return
endif
if(nv1 .NE. nv2) GOTO 200
if(nv12 .NE. nv3) GOTO 200
if(nv1 .NE. nv2) GOTO 200
if(nv1 .NE. nv4) GOTO 200
if(nv12 .NE. nv42) GOTO 200
GOTO 300
200 call mstger(r,'Lengths are incoherent')
c call calculation subroutine
300 ierr= SPMATRIX(t(ad0),
1 t(ad1),inc1,nv1,inc12,nv12,
2 t(ad2),inc2,
3 t(ad3),inc3,
4 t(ad4),inc4,inc42,
5 t(ad5))
c test return; error message if needed
if (ierr .NE. 0)call mstger(r,'Too large size')
end
c Utility subroutines : mstg0v,mstg1v,mstg2v and mstger
INCLUDE Mustig_inc.for
c calculation subroutine
integer function SPMATRIX(a0,
1 a1,inc1,li,inc12,co,
2 a2,inc2,
3 a3,inc3,
4 a4,inc4,inc42,
5 a5)
integer*4 inc1,li,inc12,co
integer*4 inc2,inc3,inc4,inc42
integer*4 a0
real*4 a1(0:1)
real*4 a2(0:1)
real*4 a3(0:1)
real*4 a4(0:1)
real*4 a5
integer*4 ada1,ada2,ada3,ada4,i0,j0
real*4 value,s,fval0
if ((li.GT.1000).OR.(co.GT.1000)) then
SPMATRIX=1
return
endif
fval0=a0
value=0.5
ada2=0
ada3=0
s=0
i0=0
j0=0
c calculation of the result matrix from the data matrix
do 10 i=1,li
ada1=i0
ada4=j0
do 20 j=1,co
a4(ada4)=a1(ada1)+value+fval0
s=s+a1(ada1)
ada1=ada1+inc12
ada4=ada4+inc42
20 continue
value=value+fval0
i0=i0+inc1
j0=j0+inc4
10 continue
a5=s
c calculation of the 1st output vector = 2nd column of the output matrix
ada4=inc42
ada1=0
do 30 i=1,li
a2(ada2)=a4(ada4)
ada2=ada2+inc2
ada4=ada4+inc4
30 continue
c calculation of the 2nd result vector = 2nd line of the output matrix
ada4=inc4
do 40 i=1,co
a3(ada3)=a4(ada4)
ada3=ada3+inc3
ada4=ada4+inc42
40 continue
SPMATRIX=0
end
Le code externe doit être une ressource de type MUEX . Son nom doit être le même que celui entré sur la face avant du module Extern. Le fichier qui contient cette ressource peut être dans le répertoire Mustig ou dans le répertoire MUSTIG overlays .
Le code doit être self-consistent et a pu être produit par tout langage (Pascal, C,...), pourvu que des bibliothèques externes n'aient pas été utilisées. L'environnement à l'appel doit être restauré quand le traitement externe est fini.
Vous pouvez lancer la routine externe en utilisant le débogueur symbolique de THINK-C : suivez les directives dans Exemples avec externes / Debug Mustig / Doc Debug.
Vous pouvez interfacer des routines Fortran avec MUSTIG en utilisant l'environnement FORTRAN ABSOFT 020 et le module Mustig Fortran. Ce dernier est utilisé exactement de la même manière que le module Extern . Voir la routine Externe Fortran pour un exemple d'interface du point de vue du code. Aussi voir les exemples Somme et Tracer dans le répertoire MUSTIG overlays .
Vous pouvez utiliser le débogueur symbolique Absoft Fortran : suivez les directives dans Exemples avec externes / Debug Mustig / Doc Debug.
La différence entre utiliser le module Fortran et utiliser le module Extern est la suivante :
Vous pouvez construire des DLL d'entrées multiples. Voir l'exemple de la matrice et le projet C associé.
La structure des routines est semblable à celle décrite dans les sections antérieures. Cependant, deux modes de chargement sont disponibles :
5-4-1. Le processus de mémoire partagée
Note : Ce mode de chargement démodé a été conservé pour assurer la compatibilité totale avec les programmes développés en utilisant des versions antérieures de Mustig. Cependant, le mode de chargement dynamique est recommandé.
Ce mode exige qu'un grand segment de mémoire partagée soit créé pour que MUSTIG puisse y construire son tableau de données. Par conséquent, assurez-vous que la configuration de votre système autorise à créer des segments de dimension suffisante dans la mémoire partagée. La dimension par défaut est 4MOctets, d'autres valeurs peuvent être entrées dans Edition / Options.
Les modules Extern et Fortran sont équivalents dans ce mode.
Ce mode est mis en cliquant sur Externes en mémoire partagée dans Edition/Options.
Le point d'entrée doit être nommé main_ext :
subroutine main_ext(t,p,r)
integer*4 p
integer*1 t(0:1)
integer*1 r(80)
.
.
main_ext(t,p,r)
char *t;
char *r;
struct {long
i,
nb_bornes,
nvar1,
d1,
nvar2,
d2,
in2,
n2;
} *p;
.
.
Les routines doivent être linkées à un sous programme délivré avec Mustig :
main_ext_f.o pour les routines du FORTRAN
main_ext_c.o pour les routines C
Des exemples de commandes du link sont:
cc -o My_routine main_ext_c.o My_Routine.c
cc -o My_routine main_ext_f.o My_Routine.f
My_Routine est la routine externe créée : son nom doit être entré dans MUSTIG sur la face avant du module Extern ou Fortran.
Note : Si une erreur se produit, ce peut être nécessaire de nettoyer les segments en utilisant les commandes UNIX ipcs et ipcrm.
Sur quelques machines, le nombre de fois qu'une routine peut être appelée est limité à 16384.
5-4-2. Le processus de chargement dynamique
Ce mode est choisi en ne cochant pas l'option Externes en mémoire artagée dans Edition/Options. Il n'exige pas qu'un grand segment de mémoire partagée soit créé. Pour permettre à la routine externe d'être gérée par le système du Lien Dynamique, il y a deux différences par rapport au processus de mémoire partagée :
My_Routine(t,p,r)
char *t;
char *r;
struct { long
i,
.
.
Cette routine peut être incluse dans un fichier source My_Routine.c . Dans ce cas, la routine My_Routine.dll compilée sera recherchée et utilisée par MUSTIG.
cc_ext My_dll
pour construire la routine.
If the external routine requires a large amount of temporary memory to work, it is recommended that you reserve this memory in MUSTIG and pass it to the routine via an input pin : just reserve a vector or a matrix of sufficient size, and use this memory segment as a "work zone".
You may however allocate memory dynamically in the external routine, but make sure you check the return value of any memory allocation function. In case of memory overflow, you must return an error message to Mustig, to prevent it from using unallocated memory. Make sure to free to allocated temporary memory before returning to Mustig.
It is NOT recommended that you use large memory arrays on the stack, or declared as static in the external routine.
If the executable external routine has the ".dll" extension, the dynamic load process is enabled. Otherwise, the shared memory process is used.
Creating the ".dll" external routines
The cc_ext UNIX command file is delivered with Mustig. A non-exhaustive list of cc_ext commands is presented below :
SUN - OS |
cc -pic - $1.c ld -o $1.dll -assert pure-text $1.o |
SUN - Solaris |
cc -Kpic -c $1.c ld -z defs -G -o $1.dll -e $1 $1.o -lm -lc |
IBM RISC 6000 |
cc -c $1.c ld -o $1.dll -e $1 $1.o |
To create an external dynamic link routine, just select the 32-bit Windows DLL target in your compiler. Browse the available compiler options to spot possible default options that may unable creating the DLL correctly.
A 32-bit compiler is required to build multiple-entry Windows DLLs. Examples of DLLs created with the WATCOM 10.5 compiler are delivered with MUSTIG.
5-6. Special PC + AU32 features
The MUSTIG_AU32 version allows to monitor the OROS_AU32 TMSC320 DSP board directly from Mustig. The Mustig program is automatically transferred to the AU32 board at run time. This version allows to create custom real-time applications while taking advantage of Mustig's legendary user-friendliness and easiness of use.
The so-called Mixed version allows to switch between the AU32 board and the PC for running the programs : the user can tune up an application on the PC and send it to the AU32 board when ready.
You may create external routines in the AU32 version too : these will be automatically transferred to the OROS AU32 DSP board at run time. The Edit / Options / Calculations dialog box features two additional fields :
Important note : This memory amount, as well as the memory amount reserved for the code, may be changed only if no data is stored. Thus, it is necessary to clear the data by clicking on the program window and launch the Clear the box command in the Calculations menu.
.tms external routine for the AU32 boardIf the routine name entered in the Extern MUSTIG module is My_Routine, MUSTIG searches in the current directory for the executable My_Routine.tms file. The latter must have been produced by a My_Routine.c source file including the declaration
void My_Routine(t,p,r)
The command line used for building the My_Routine.tms routine is :
cl30 -g -mi My_Routine sub1 .... -z -r -cr -o My_Routine.tms -l \c30tools\rts30.lib
where sub1.c, ..., are the subprograms used by My_Routine.c.
Example
The matrix.c external routine (see Example of interfaced external routine) is provided as an example in the extern directory. Both executable routines matrix.dll (running on the PC) and matrix.tms (running on the AU32 board) must be in the same directory as matrix.mtg, the calling MUSTIG program.
The following files are available in the ext_tms subdirectory :