Obligement - L'Amiga au maximum

Dimanche 19 novembre 2017 - 05:48  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Hit Parade
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Articles divers

 · Articles in english
 · Articles in other languages


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Moteurs de recherche
 · Pages de liens
 · Constructeurs matériels
 · Matériel
 · Autres sites de matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Développeurs logiciels
 · Logiciels
 · Développeurs de jeux
 · Jeux
 · Autres sites de jeux
 · Scène démo
 · Divers
 · Informatique générale


Jeux Amiga

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


Trucs et astuces

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


Glossaire

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


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Contact

David Brunet

Courriel

 


Programmation : Amiga E - programmer ARexx
(Article écrit par Yann Armand et Pierre Girard et extrait d'Amiga News - février 1996)


Il y a de grandes chances pour que vous connaissiez tous ARexx. Pour ceux qui ne se souviennent pas, voici un petit rappel. ARexx est un langage de programmation simple à utiliser et qui permet de communiquer avec les programmes prévus à cet effet.

Il permet notamment d'ajouter des fonctions personnelles aux logiciels par le biais de scripts (des sortes de macro-commandes en plus puissant). En théorie, l'Amiga était déjà capable de faire communiquer les tâches entre elles par l'intermédiaire des ports de message Exec. Cependant, il n'y avait pas de standard de communication. Et ARexx est arrivé ! Mais quel est l'intérêt de programmer ARexx ?

C'est simple : prenez un petit script ARexx qui ouvre une fenêtre de requête sous GoldEd. Ça va vite, même si le programme est interprété. Mais si vous voulez, par exemple, chercher un mot spécifique dans un dictionnaire avec une énorme boucle WHILE, vous pouvez aller prendre un café en attendant.

Eh oui, le problème d'ARexx, c'est la vitesse. En utilisation normale, celle-ci est tout à fait convenable. Mais notre optique à nous est de ne pas être ralenti par l'interpréteur.

Nous vous livrons donc ce mois-ci la méthode pour qu'un petit programme (le nôtre) puisse communiquer avec un logiciel quelconque, tout en ne connaissant que les commandes que ce logiciel met à la disposition d'ARexx et en se substituant à l'interpréteur (RexxMast).

Les ports de messages

Pour programmer ARexx, il faut au minimum avoir quelques notions sur les ports de messages. Ils servent à recevoir des messages, à intercepter des événements. C'est ainsi qu'une fenêtre possède un port de message qui intercepte les événements Intuition lorsque ceux-ci surviennent (déplacement...). La gestion d'un port peut paraître ardue à première vue, mais quelques commandes de la bibliothèque Exec se chargent de tout contrôler.

Les commandes de gestion des ports

La première chose à faire est de déterminer si notre port existe déjà grâce à la fonction FindPort('nom').

Attention : cette commande doit toujours être encadrée du couple Forbid()-Permit() coupant le multitâche. Le port n'existant pas, il faut le créer grâce à la fonction CreateMsgPort() qui nous renvoie une structure MsgPort. Il faut ensuite appeler la fonction AddPort() afin d'ajouter le nouveau port à la liste des ports publics (pour que les autres tâches puissent y avoir accès). Dans l'ordre inverse, il nous faudra sortir le port de la liste des ports publics (RemPort) puis l'effacer (DeleteMsgPort) avant la sortie du programme.

Les messages ARexx

Les tâches communiquent par ARexx en s'envoyant des objets de type rexxmsg. Ceux-ci contiennent un objet node exec standard, le type d'action ARexx demandé, le nom de la commande sous forme d'une chaîne de caractères, deux champs results (chaînes) et l'adresse du port de message pour la réponse.

Envoi du message ARexx

En cadeau ce mois-ci, voici une superbe procédure qui va vous permettre d'envoyer des commandes ARexx à vos programmes préférés. La commande se déclare comme suit :

PROC sendrexxcmd(hostname,replyport: PTR TO mp, command, flags, result)

. hostname, est le nom du port Arexx appelé.
. replyport, l'adresse du port sur lequel doit se faire la réponse.
. command, est la chaîne de caractères décrivant la commande.
. retour, est l'adresse de la chaîne de caractères dans laquelle sera stocké le résultat.

Il nous faut créer un objet rexxmsg. Une fois remplis ces champs, nous l'expédions à la tâche-cible (hostname), qui nous répondra sur notre port de message(replyport).

Bon allez, on explique

On commence par allouer l'objet rexxmsg. Cela se fait presque tout seul grâce à CreateRexxMsg auquel nous donnons comme arguments notre port de message ainsi que son nom.

On crée ensuite la chaîne d'arguments (CreateArgstring). Et là, tout le monde se demande pourquoi on fait un CopyMem alors qu'il suffirait d'écrire :

rxmsg.args={rexx_command}

On atteint ici une des limites de l'Amiga E. En effet, rxmsg.args est déclaré dans le module "rexx/storage" comme une substructure. C'est donc, pour le compilateur, le label d'une substructure dont il ne connaît pas le contenu. Il pourrait faire ainsi des erreurs de typage pour toute instruction d'affectation. Par contre, nous, nous savons que c'est un tableau de 16 pointeurs sur des chaînes de caractères. Nous posons donc dans la première case du tableau (le premier argument) l'adresse de la chaîne d'arguments que nous venons de créer. Nous continuons en définissant le type d'action ARexx. C'est une commande (RXCOMM) avec d'éventuels flags (drapeaux), le plus souvent utilisé étant RXFF_RESULT qui demande un résultat sous forme d'une chaîne de caractères.

Comme nous sommes des fanatiques du Shell, nous définissons stdin et stdout avec Input() et Output() ce qui permettra à notre programme d'utiliser des pipes, vous savez "dir | more".

Et là, on envoie le message ! Attention, quand on fait ce genre de chose, il faut s'assurer que les ports ne vont pas changer pendant l'opération (Forbid-Permit). Ensuite, on cherche l'adresse du port grâce à son nom (FindPort()) et on envoie avec PutMsg(...).

Enfin, on attend une réponse (WaitPort, GetMsg). La tâche-cible nous a renvoyé notre message dans lequel elle a rempli les deux champs result :
  • result1 pour la réussite de l'action (0), sinon un code de retour standard ARexx.
  • result2 pour la chaîne de résultat, si elle a été demandée.
Notez dans vos cahiers pour le mois prochain que vous avez à modifier la procédure pour qu'elle traite le cas où rxmsg.result1 est différent de 0, c'est-à-dire quand il y a une erreur. Il nous suffit pour finir de recopier result2 dans la chaîne servant au retour (StrCopy), de nettoyer le message (ClearRexxMsg) et de désallouer la mémoire (DeleteRexxMsg).

Voili, voilou, c'est fini. Si vous ne possédez pas CygnusEd (commercial), vous pouvez utiliser GoldEd avec par exemple :

sendrexxcmd('GOLDED.1',replyport,'QUERY FILE', RXFF_RESULT,nom).

Le mois prochain, nous verrons peut-être une application de cette routine. Tchao.

MODULE 'exec/ports','exec/nodes','exec/lists'
MODULE 'rexxsyslib','rexx/rxslib','rexx/storage','rexx/errors'
MODULE 'dos/dos'

/************************* main ***********************/
PROC main() HANDLE
DEF replyport:PTR TO mp
DEF node:PTR TO ln
DEF nom[64]:STRING
    IF (rexxsysbase:=OpenLibrary('rexxsyslib.library',0))=NIL THEN Raise(0)
->Creation du port public
    Forbid()
    IF FindPort('Rexx_Comp')=0
        IF replyport:=CreateMsgPort()
            node:=replyport.ln
            node.name:='Rexx_Comp'
            node.pri:=0
            AddPort(replyport)
        ENDIF
    ELSE
        Raise()
    ENDIF
    Permit()
->Recherche du port 'rexx_ced'
    Forbid()
    IF FindPort('rexx_ced') THEN WriteF('Port "rexx_ced" Trouvé') 
        ELSE WriteF('Port "rexx_ced" introuvable')
    Permit()
->Envoi de commande a cygnus
    sendrexxcmd('rexx_ced',replyport,'STATUS 21',RXFF_RESULT,nom)
    WriteF('Le fichier ouvert sous cygnus est   ',nom)
->Fermeture des MsgPorts et des Libraries
    RemPort(replyport)
    DeleteMsgPort(replyport)
    CloseLibrary(rexxsysbase)
EXCEPT
        WriteF('error')
ENDPROC
/****************** sendrexxcmd **********************/
PROC sendrexxcmd(hostname,replyport:PTR TO mp,command,flags,retour)
DEF rxmsg:PTR TO rexxmsg
DEF replymsg:PTR TO rexxmsg
DEF rexx_command:LONG
DEF hostport:PTR TO mp
DEF node:PTR TO ln
-> Creation du message AREXX
        node:=replyport.ln
        IF (rxmsg:=CreateRexxMsg(replyport,NIL,node.name))=NIL THEN Raise(0)
        IF rexx_command:=CreateArgstring(command,EstrLen(command))
            CopyMem({rexx_command},rxmsg.args,4)
            rxmsg.action:=RXCOMM OR flags
            rxmsg.stdin:=Input()
            rxmsg.stdout:=Output()
-> Envoi du message
                Forbid()
                hostport:=FindPort(hostname)
                IF hostport THEN PutMsg(hostport,rxmsg)
                Permit()
-> Recuperation du resultat
                WaitPort(replyport)
                replymsg:=GetMsg(replyport)
        ELSE
                WriteF('Problème d''envoi de commande Arexx')
        ENDIF
        StrCopy(retour,replymsg.result2,ALL)
        ClearRexxMsg(rxmsg,16)
        DeleteRexxMsg(rxmsg)
ENDPROC


[Retour en haut] / [Retour aux articles] [Article précédent] / [Article suivant]