Suivez-nous sur X
|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : Amiga E - création d'un module
(Article écrit par Pierre Girard et extrait d'Amiga News - novembre 1996)
|
|
Depuis le temps que cette rubrique existe, vous avez sans doute réalisé vos propres routines dont vous vous servez souvent.
Ce mois-ci, je vous propose de créer un module incluant vos fonctions favorites afin de les écrire une fois pour toutes.
Avez-vous déjà utilisé le petit programme ShowModule fourni avec le paquetage du E ? Si oui, vous avez sans doute remarqué
qu'un module (autre que les modules décrivant les bibliothèques de fonctions de l'Amiga) comprend le plus souvent des
procédures. Ce sont en fait des fonctions que l'on peut appeler directement, à condition d'avoir défini le module à charger
en début de programme. Mais on peut aussi définir d'autres données dans un module, comme un objet (structure) ou des constantes
qui n'ont alors plus besoin d'être définies dans le corps du programme.
L'export (ancien cochon ?)
Quand on crée un nouveau module, toutes les données incluses dans celui-ci sont privées par défaut. C'est-à-dire que les
informations ou les procédures créées sont destinées au module lui-même, à usage interne. Si l'on veut que l'utilisateur ait
accès à ces données, il faut le préciser grâce au mot-clé EXPORT. Ainsi, il suffit de mettre EXPORT devant les procédures
appelables par l'utilisateur. Celui-ci n'a pas à se soucier de comment ça marche... ça marche, c'est tout. On se rapproche
de la programmation objet, puisque tant que les paramètres de la fonction appelée sont les mêmes, cela fonctionnera toujours,
même si les routines changent ! (voir le chapitre 14C. de la doc du E sur le DATA-HIDING). C'est pareil pour les variables
qui peuvent être définies privées ou publiques, à condition qu'elle soient globales. Les variables locales sont toujours
privées. Il est conseillé d'utiliser le moins possible les variables globales, car on prend le risque qu'il y ait conflit
avec un autre module ou le programme appelant. Si vous n'avez pas le choix, veillez bien à ce que le nom de cette variable
n'existe pas déjà dans un autre module. Les constantes sont quant à elles toujours publiques (forcément !).
Poupées gigognes
Tout comme les poupées russes, les modules peuvent en contenir d'autres, mais la comparaison s'arrête là. On peut en effet
utiliser des modules dans l'élaboration d'un module si, par exemple, une procédure requiert des constantes ou des décalages
de bibliothèques. Cela permet à l'utilisateur d'utiliser les fonctions de ce module, sans avoir à se soucier en plus de ce
dont a besoin le module en question. Les liens de dépendance ainsi créés peuvent se vérifier avec la commande ShowModule.
Là où l'affaire se corse, c'est quand un module A a besoin d'un module B, et que ce dernier ne comprend pas uniquement des
constantes, objets ou bibliothèques, mais aussi des procédures. A la recompilation de B, il est alors souvent nécessaire de
recompiler A quand les décalages changent.
Deluxe Paint XII
Les petits programmes explicatifs de ce mois-ci montrent comment créer un module avec quelques fonctions graphiques de base
(je sais, je ne me suis pas trop fatigué pour faire ces malheureux rectangles et autres cercles !). Le programme en lui-même
que j'ai modestement appelé "Deluxe Paint XII" ne vous permet même pas de dessiner mais juste d'appeler les fonctions présentes dans
le module. L'interface est simple (mais efficace) mais le reste demande quelques explications. Tout d'abord, pour ne pas
refaire ce qui a déjà été fait, je me sers du module tools/clonescreen afin de dupliquer l'écran du Workbench. Une fois l'écran
ouvert, il reste à trouver l'adresse du Rastport indispensable aux fonctions de la graphics.library (je sais, j'aurais pu le
faire dans le module). Les procédures carrés, cercles et points ne font qu'appeler les fonctions square, circles et rndpoints
du module Easygraph.
Conclusion
Vous voilà prêts pour mettre au point vos propres modules. Je vous conseille de regarder le répertoire sources/tools du E, vous
y découvrirez les sources de quelques modules. Pour finir, une petite astuce. Vous pouvez charger des modules qui sont placés
ailleurs que dans emodules : en ajoutant * devant le chemin. Rendez-vous le mois prochain ! Bye.
/* MODULE Easygraph */
OPT MODULE
MODULE 'intuition/screens','intuition/intuition','graphics/modeid'
EXPORT PROC cls(rast)
Move(rast,0,18)
ClearScreen(rast)
ENDPROC
EXPORT PROC square(rast,ltx,lty,size)
Move(rast,ltx,lty)
Draw(rast,ltx+size,lty)
Draw(rast,ltx+size,lty+size)
Draw(rast,ltx,lty+size)
Draw(rast,ltx,lty)
ENDPROC
EXPORT PROC circle(rast,x,y,size)
DrawEllipse(rast,x,y,size,size)
ENDPROC
EXPORT PROC rndpoints(rast,x,y,size)
DEF i
FOR i:=1 TO 10000
WritePixel(rast,x+Rnd(size),y+Rnd(size))
ENDFOR
ENDPROC
/* Deluxe Paint XII */
MODULE '*easygraph','intuition/screens','intuition/intuition'
MODULE 'intuition/intuitionbase','tools/clonescreen'
DEF scr:PTR TO screen,rast,intbase:PTR TO intuitionbase
DEF i,s,win,font,reponse
ENUM ERR_NONE,ERR_SCREEN,ERR_WIN
ENUM BYE,CLS,CARRES,CERCLES,POINTS
PROC main() HANDLE
intbase:=intuitionbase
s,font:=openclonescreen('Workbench','Oh le beau dessin')
scr:=intbase.firstscreen
rast:=scr.rastport
IF (win:=backdropwindow(s))=NIL THEN Raise(ERR_WIN)
WHILE (reponse:= EasyRequestArgs (win, [SIZEOF easystruct, 0,
'Test du module EasyDraw',
'Quoi toi vouloir voir ?',
'CLS|Carrés|Cercles|Points|Bye'],0,0)) <>BYE
SELECT reponse
CASE CLS
cls(rast)
CASE CARRES
carres()
CASE CERCLES
cercles()
CASE POINTS
points()
ENDSELECT
ENDWHILE
closeclonescreen(s,font,win)
EXCEPT
closeclonescreen(s,font,win)
ENDPROC
PROC carres()
FOR i:=100 TO 150 STEP 4
square(rast,300,i,i/2)
ENDFOR
ENDPROC
PROC cercles()
FOR i:=100 TO 200 STEP 4
circle(rast,320,300-i,i/4)
ENDFOR
ENDPROC
PROC points()
rndpoints(rast,10,10,100)
ENDPROC
Listing du mois dernier (oops!)
/* Envoie d'une chaîne de caractères au clipboard.device */
MODULE 'devices/clipboard',
'exec/io',
'exec/memory',
'exec/ports'
ENUM ERR_NONE, ERR_ARG, ERR_PORT, ERR_IO, ERR_DOIO, ERR_LEN
DEF message:PTR TO mp
DEF ior:PTR TO ioclipreq
DEF length, slen, odd
DEF text[160]:STRING
DEF arguments[5]:ARRAY OF LONG
DEF rdargs
PROC putlong(ior:PTR TO ioclipreq, longdata)
ior.data:=longdata
ior.length:=4
ior.command:=CMD_WRITE
IF DoIO(ior)<>0 THEN Raise(ERR_DOIO)
IF ior.actual<>4 THEN Raise(ERR_LEN)
ENDPROC
PROC main() HANDLE
IF rdargs:=ReadArgs('/A',arguments,NIL)=0 THEN Raise(ERR_ARG)
StrCopy(text,arguments[0],ALL)
FreeArgs(rdargs)
IF (message:=CreateMsgPort())=0 THEN Raise(ERR_PORT)
IF (ior:=CreateIORequest(message,SIZEOF ioclipreq))=0 THEN Raise(ERR_IO)
OpenDevice('clipboard.device', 0, ior, 0)
slen:=StrLen(text)
odd:=Odd(slen) -> longueur impaire ?
IF odd THEN length:=slen+1 ELSE length:=slen
-> Valeurs initiales pour décalage, error, et clipid
ior.offset:=0
ior.error:=0
ior.clipid:=0
-> Préparation du header IFF
putlong(ior, 'FORM') -> 'FORM'
length:=length+12 -> Longueur texte + 'FORMFTXTCHRS'
putlong(ior, {length}) -> Total length
putlong(ior, 'FTXT') -> 'FTXT'
putlong(ior, 'CHRS') -> 'CHRS'
putlong(ior, {slen}) -> String length
-> écriture de la chaîne
ior.data:=text
ior.length:=slen
ior.command:=CMD_WRITE
IF DoIO(ior)<>0 THEN Raise(ERR_DOIO)
-> on remplit un caractère de plus si longueur impaire
IF odd
ior.data:=''
ior.length:=1
DoIO(ior)
ENDIF
-> On dit au clipboard qu'on a fini d'écrire
ior.command:=CMD_UPDATE
IF DoIO(ior)<>0 THEN Raise(ERR_DOIO)
CloseDevice(ior)
DeleteIORequest(ior)
DeleteMsgPort(message)
EXCEPT
WriteF('Une erreur est apparu de code: \d\n',exception)
IF ior THEN CloseDevice(ior)
IF ior THEN DeleteIORequest(ior)
IF message THEN DeleteMsgPort(message)
ENDPROC
|
|