Lier Erlang avec d`autres langages de programmation
Transcription
Lier Erlang avec d`autres langages de programmation
16 Lier Erlang avec d’autres langages de programmation Les logiciels actuels, quelle que soit leur taille, sont souvent écrits dans plusieurs langages de programmation. Généralement, les pilotes de périphériques sont écrits en C et de nombreux environnements de développement intégrés comme Eclipse sont écrits en Java ou en C# ; les applications web peuvent être développées en Ruby et en PHP. De son côté, Erlang permet d’offrir une concurrence légère et résistante aux pannes et, pour manipuler ou analyser efficacement des chaînes de caractères, Perl et Python sont la norme. Par ailleurs, si la bibliothèque dont vous avez besoin pour résoudre un problème n’existe pas dans votre langage favori, vous devrez alors choisir entre utiliser une bibliothèque externe ou tout recoder vous-même en Erlang1. La communication entre les langages n’est jamais simple, qu’il s’agisse du langage naturel ou des langages de programmation. Avec le premier, il faut comprendre comment chaque langue fonctionne – utilise-t-elle des articles ? Différencie-t-elle le genre ? Où sont placés les verbes dans une phrase ? Il faut également savoir traduire les mots – le verbe ser du portugais signifie-t-il la même chose que "être" en français ? (La réponse est non.) Il en va de même pour les langages de programmation : quel paradigme utilisent-ils ? Sont-ils fonctionnels, orientés objet, concurrents ou structurés ? Est-ce qu’un entier Java est identique à un entier Erlang ? (La réponse est non !) En outre, cette communication entre les langages n’est pas tout ; Erlang/OTP permet également de communiquer en utilisant XML, ODBC, CORBA, ASN et SNMP, qui aident Erlang dans son rôle sans cesse croissant de "colle distribuée" pour relier des programmes monothreads classiques. 1. C’est ce que fait Wrangler, l’outil de refactoring pour Erlang, pour détecter le code dupliqué : il utilise une bibliothèque C efficace pour identifier les "clones" éventuels dans le code Erlang. © 2010 Pearson France – Programmer en Erlang – Francesco Cesarini, Simon Thompson Livre Erlang.indb 361 31/08/10 13:13 362 Programmer en Erlang Présentation du problème Erlang fournit un certain nombre de mécanismes pour travailler avec plusieurs langages : un modèle de haut niveau reposant sur des nœuds Erlang distribués, un modèle de plus bas niveau permettant de communiquer avec un programme externe par un port et un mécanisme permettant de lier des programmes – les pilotes liés – dans la machine virtuelle elle-même. Le modèle de programmation distribuée d’Erlang offre une solution à la fois simple et souple au problème du fonctionnement des autres langages avec Erlang : les programmes écrits dans d’autres langages s’exécutent dans d’autres nœuds sur la même machine ou sur des machines différentes et apparaissent comme des nœuds Erlang distribués qui envoient et reçoivent des messages. Ces nœuds offrent un environnement dans lequel les programmes externes peuvent s’exécuter, mais également communiquer avec des nœuds Erlang. Pour que cet échange avec un programme écrit dans un autre langage fonctionne, on peut utiliser des ports ou fournir un modèle plus élaboré des primitives de communication Erlang dans cet autre langage. Dans les deux cas, il faut savoir comment gérer les types de base et traduire les structures de données composées entre les deux langages. Dans ce chapitre, nous verrons comment construire des nœuds en Java et en C qui peuvent interagir avec Erlang. Nous présenterons également erl_call, qui permet au shell Unix de communiquer avec un nœud Erlang distribué et qui repose sur la bibliothèque erl_interface fournie avec Erlang, tout comme le paquetage Java JInterface. Ces bibliothèques offrent un code et une architecture stables aux dépens de la vitesse pure. Puis nous expliquerons comment communiquer au moyen des ports et nous donnerons un exemple d’interaction avec Ruby en nous servant de la bibliothèque erlectricity. Autres langages Ce chapitre traite des interactions avec Java, C et Ruby, mais Erlang peut être lié à un grand nombre d'autres langages de programmation : • OTP.NET fournit un lien vers la plateforme .NET, via un portage du code de JInterface. • Py-Interface, une implémentation Python d'un nœud Erlang, permet de faire communiquer ces deux langages. • Le Perl Erlang-Port permet à du code Perl de communiquer avec Erlang via un port. • PHP/Erlang est une extension PHP fournissant un ensemble de fonctions pour transformer un thread PHP en nœud Erlang C. • Haskell/Erlang-FFI autorise une communication complète et dans les deux sens entre des programmes écrits en Haskell et en Erlang. Les messages envoyés depuis Haskell vers Erlang ressemblent à des appels de fonctions et les messages envoyés d'Erlang à Haskell sont délivrés à des MVar. • L'interface Erlang/Gambit permet de faire communiquer Scheme et Erlang. • Distel améliore le mode Erlang d'Emacs en autorisant l'interaction entre Emacs Lisp et Erlang. © 2010 Pearson France – Programmer en Erlang – Francesco Cesarini, Simon Thompson Livre Erlang.indb 362 31/08/10 13:13 Chapitre 16 Lier Erlang avec d’autres langages de programmation 363 Pour obtenir une interaction la plus efficace possible, vous pouvez définir un pilote lié. Cependant, un pilote lié mal écrit pouvant provoquer des fuites mémoire, figer ou crasher tout le système d’exécution d’Erlang, ces pilotes doivent être utilisés avec la plus grande prudence. Interagir avec Java Le paquetage Java JInterface offre à Java un modèle de processus et de communication à la Erlang. Vous pouvez l’utiliser seul pour bénéficier de la concurrence de type Erlang en Java, ou comme composante d’un système distribué mélangeant les deux langages afin d’intégrer des composants Erlang dans un système Java et vice versa. JInterface est une collection de classes Java dont les noms commencent quasiment tous par Otp. Cette section décrira les plus utilisées et donnera des exemples d’envoi de messages et de gestion des types de données entre les deux langages. Vous trouverez plus d’informations sur JInterface et ses classes Erlang dans la section "Interface and Communication Applications" de la documentation d’Erlang/OTP. Le fil rouge de cette section sera une réécriture de l’exemple d’appel de procédure distante (RPC) du Chapitre 11. Nœuds et boîtes aux lettres Nous avons décrit les nœuds Erlang au Chapitre 11, qui a également présenté la programmation distribuée. Un nœud Erlang est désigné par son nom, constitué d’un identifiant suivi d’un nom d’hôte (au format court ou long) ; chaque hôte peut exécuter plusieurs nœuds, pourvu que leurs noms soient différents. La classe OtpNode est la représentation JInterface d’un nœud Erlang : OtpNode machin = new OtpNode("machin"); Cette instruction crée l’objet Java machin – que nous appellerons un nœud –, qui représente le nœud Erlang machin qui s’exécute sur la machine sur laquelle elle est exécutée. Vous pouvez créer un processus sur ce nœud en créant une boîte aux lettres, représentée par un identifiant de processus ou enregistrée sous un certain nom. L’instruction suivante crée un processus : OtpMbox mbox = machin.createMbox(); Pour donner un nom à cette boîte, il suffit de passer une chaîne en paramètre : OtpMbox mbox = machin.createMbox("serveurfacto"); L’enregistrement peut également s’effectuer après la création : mbox.registerName("serveurfacto"); © 2010 Pearson France – Programmer en Erlang – Francesco Cesarini, Simon Thompson Livre Erlang.indb 363 31/08/10 13:13 364 Programmer en Erlang Dans les deux cas, le processus est enregistré sous le nom serveurfacto. Nous l’avons nommé ainsi car il agira comme un "serveur de factorielles" en renvoyant la factorielle des entiers qu’il reçoit aux processus qui les ont envoyés. Vous pouvez désormais accéder à cette boîte aux lettres par son nom. Si vous avez également besoin de son identifiant de processus – pour un nœud Erlang distant, par exemple –, utilisez sa méthode self() : OtpErlangPid pid = mbox.self(); Représentation des types Erlang Le paquetage JInterface contient plusieurs classes pour représenter les différents types Erlang en Java. Leurs méthodes permettent de convertir les types natifs dans ces représentations et réciproquement, ce qui est essentiel à l’interaction entre les deux langages. Nous avons déjà vu un exemple dans l’instruction précédente : la classe OtpErlang Pid produit la représentation Java d’un identifiant de processus Erlang. De même, les classes OtpErlangAtom, ..., OtpErlangTuple, OtpErlangObject permettent de représenter les atomes, les binaires, les listes, les ports, les références, les tuples et les termes. Les types points flottants d’Erlang sont convertis en OtpErlangFloat ou OtpErlang Double ; les types entiers en OtpErlangByte, OtpErlangChar, OtpErlangShort, OtpErlangInt, OtpErlangUInt ou OtpErlangLong, selon la valeur et le signe de la valeur concernée. La classe OtpErlangBoolean permet de représenter les deux atomes spéciaux true et false et les chaînes Erlang – qui ne sont que des listes d’entiers – sont décrites par la classe OtpErlangString. Tous les détails de ces classes se trouvent dans la documentation de JInterface ; nous les utiliserons dans la prochaine section et dans l’exemple RPC. Communication Les processus Erlang envoient et reçoivent des messages ; dans JInterface, ces opérations sont implémentées par les méthodes send et receive d’une boîte aux lettres. Les messages échangés sont des termes Erlang et sont donc représentés par des objets OtpErlangObject en Java. L’envoi du message suivant dans le processus mbox : Pid ! {ok, M} sera donc traduit par : mbox.send(pid,tuple); © 2010 Pearson France – Programmer en Erlang – Francesco Cesarini, Simon Thompson Livre Erlang.indb 364 31/08/10 13:13 Chapitre 16 Lier Erlang avec d’autres langages de programmation 365 où la variable Java pid correspond à la variable Erlang Pid, et tuple2 représente le terme Erlang {ok, M}. Un message est reçu par une instruction de la forme : OtpErlangObject o = mbox.receive(); Cette instruction est différente d’un receive Erlang car elle n’effectue aucun pattern matching sur le message. Nous verrons dans l’exemple suivant comment décomposer et analyser ce message. Récapitulatif : RPC revisité Le code Erlang suivant met en place un serveur de factorielles sur le nœud machin de l’hôte STC : setup() -> spawn('machin@STC',monrpc,serveur,[]). serveur() -> register(serveurfacto,self()), factoLoop(). factoLoop() -> receive {Pid, N} -> Pid ! {ok, facto(N)} end, factoLoop(). Le serveur reçoit des messages de la forme {Pid, N} et renvoie le résultat {ok, facto(N)} au processus identifié par Pid. Voici le code Java qui effectue le même travail : 1 import com.ericsson.otp.erlang.*; // Pour JInterface 2 import java.math.BigInteger; // Pour la factorielle 3 4 public class NoeudServeur { 5 6 public static void main (String[] _args) throws Exception{ 7 8 OtpNode machin = new OtpNode("machin"); 9 OtpMbox mbox = machin.createMbox("serveurfacto"); 10 11 OtpErlangObject o; 12 OtpErlangTuple msg; 13 OtpErlangPid de; 2. Si vous programmez en Erlang depuis plusieurs années et que vous soyez troublé par le fait que des variables comme pid et tuple sont toutes en minuscules, vous n’êtes pas seul. Ce qui est important, ici, est que vous ne les preniez pas pour des atomes. © 2010 Pearson France – Programmer en Erlang – Francesco Cesarini, Simon Thompson Livre Erlang.indb 365 31/08/10 13:13 366 Programmer en Erlang 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 } 30 } BigInteger n; OtpErlangAtom ok = new OtpErlangAtom("ok"); while(true) try { o = mbox.receive(); msg = (OtpErlangTuple)o; de = (OtpErlangPid)(msg.elementAt(0)); n = ((OtpErlangLong (msg.elementAt(1))).bigIntegerValue(); OtpErlangObject[] reponse = new OtpErlangObject[2]; reponse[0] = ok; reponse[1] = new OtpErlangLong(Facto.facto(n)); OtpErlangTuple tuple = new OtpErlangTuple(reponse); mbox.send(de,tuple); }catch(OtpErlangExit e) {break; } Dans cet exemple, les aspects concurrents sont marqués en gras aux lignes 8, 9, 18 et 26 ; le reste sert à analyser, à décomposer et à reconstruire les valeurs des données et à créer la boucle de contrôle. Le programme principal commence par lancer un nœud machin et un processus serveurfacto sur ce nœud. La boucle qui s’étend de la ligne 18 à la ligne 26 reçoit et répond à un message. Le message reçu est un terme Erlang, c’est-à-dire un OtpErlangObject, qui est transtypé en OtpErlangTuple à la ligne 19 pour pouvoir en extraire l’identifiant de l’expéditeur (ligne 20) et l’entier envoyé (ligne 21). Cette valeur est extraite comme un entier long mais est convertie en BigInteger pour permettre le calcul de sa factorielle. Le reste du code (lignes 22 à 26) construit et envoie le tuple reponse. La ligne 22 crée un tableau d’objets contenant la représentation de l’atome ok (ligne 23) et la valeur renvoyée par facto(n) (ligne 24). Ce tableau est ensuite reconverti en tuple (ligne 25) avant d’être renvoyé au client à la ligne 26. Interactions Pour interagir avec le nœud Java, vous pouvez utiliser le code suivant et appeler la fonction monrpc:f/1 à partir du shell Erlang : -module(monrpc). ... f(N) -> {serveurfacto, 'machin@STC'} ! {self(), N}, receive {ok, Res} -> io:format("La factorielle de ~p est ~p.~n", [N,Res]) end. © 2010 Pearson France – Programmer en Erlang – Francesco Cesarini, Simon Thompson Livre Erlang.indb 366 31/08/10 13:13 Chapitre 16 Lier Erlang avec d’autres langages de programmation 367 Ce code client est exactement le même que celui qui permet d’interagir avec un nœud Erlang ; un "test de Turing"3 envoyant des messages au nœud ou en recevant de celui-ci devrait être incapable de faire la différence entre un nœud Java et un nœud Erlang. Notes de bas de page Nous expliquerons dans cette section comment utiliser correctement JInterface dans vos programmes. Pour établir et gérer les connexions entre les nœuds Java et Erlang, il faut d’abord que (Erlang Port Mapper Daemon) s’exécute – vous pouvez le lancer en tapant simplement epmd (la version Windows du programme s’appelle epmd.exe) et tester qu’il s’exécute déjà à l’aide de la commande suivante : epmd epmd -names Vous obtiendrez alors la liste des nœuds Erlang qui s’exécutent sur la machine et vous pourrez donc vérifier qu’un nœud a bien été lancé. Le système créera un nœud avec le cookie par défaut si vous n’en fournissez pas. Pour créer un nœud avec un cookie précis, utilisez une instruction de la forme : OtpNode machin = new OtpNode("machin", "valeur-cookie"); S’il faut utiliser un port particulier, celui-ci sera passé en troisième paramètre. La ligne 1 du programme de la section "Récapitulatif : RPC revisité" importait le paquetage JInterface, mais il faut également indiquer son emplacement au compilateur et à la machine virtuelle car il fait partie de la distribution OTP, pas de la distribution Java. Son chemin est de la forme : <racine-otp>/jinterface-XXX/priv/OtpErlang.jar où <racine-otp> est le répertoire racine de la distribution, tel qu’il est renvoyé par l’appel code:root_dir() dans un nœud, et XXX est le numéro de version. Sur Mac OS X, ce chemin est le suivant : /usr/local/lib/erlang/lib/jinterface-1.4.2/priv/OtpErlang.jar Voici comment indiquer ce chemin au compilateur : javac -classpath ".:/usr/local/lib/erlang/lib/jinterface-1.4.2/priv/OtpErlang. jar" NoeudServeur.java 3. Le test de Turing a été créé par le mathématicien pionnier de l’informatique Alan Turing (1912-1954) pour tester l’intelligence d’une machine. L’idée, traduite en technologie moderne, est que le testeur discute sans les voir avec deux "interlocuteurs" en ligne – une personne et une machine : s’il ne peut pas reconnaître formellement qui est l’humain et qui est la machine, la machine est considérée comme faisant preuve d’intelligence. © 2010 Pearson France – Programmer en Erlang – Francesco Cesarini, Simon Thompson Livre Erlang.indb 367 31/08/10 13:13 368 Programmer en Erlang et à la machine virtuelle Java : java -classpath ".:/usr/local/lib/erlang/lib/jinterface-1.4.2/priv/OtpErlang. jar" NoeudServeur Pour aller plus loin JInterface a bien d’autres possibilités que celles que nous venons de voir : ■■ Les méthodes link et unlink d’OtpMbox permettent, respectivement, de se lier et de se libérer d’une boîte aux lettres Java ou d’un processus Erlang. ■■ Notre exemple suppose que les connexions entre les nœuds sont créées automatique- ment. Vous pouvez également utiliser la méthode ping sur un nœud afin de tester si un nœud distant existe : en ce cas, la connexion est automatique. ■■ Vous pouvez envoyer des données quelconques entre les nœuds en passant par des données binaires, qui seront gérées par la classe OtpErlangBinary. ■■ La classe OtpConnection fournit un mécanisme de haut niveau pour les RPC, exac- tement comme le fait le module rpc pour Erlang. ■■ Les méthodes d’OtpConnection permettent également de tracer l’exécution. Toutes ces fonctionnalités sont décrites en détail avec les autres dans la documentation en ligne. Nœuds C La bibliothèque C erl_interface permet de construire des termes binaires Erlang encodés en C, d’y accéder et de les manipuler. Elle fournit également des fonctions pour gérer l’allocation mémoire, accéder aux noms globaux et signaler les erreurs : ■■ erl_marshal, erl_eterm, erl_format et erl_malloc permettent de gérer le for- mat des termes Erlang, notamment la gestion mémoire. Ces fonctions autorisent également la conversion des termes Erlang en structures C et réciproquement. ■■ erl_connect et ei_connect permettent de se connecter à Erlang via un nœud Erlang distribué. ■■ erl_error affiche les messages d’erreur. ■■ erl_global donne accès aux noms globaux. ■■ registry permet de stocker et de sauvegarder des paires clé-valeur. On retrouve ainsi une partie des fonctionnalités des tables ETS, et ces paires peuvent être sauvegardées et restaurées avec une table Mnesia sur un nœud Erlang lié. © 2010 Pearson France – Programmer en Erlang – Francesco Cesarini, Simon Thompson Livre Erlang.indb 368 31/08/10 13:13 Chapitre 16 Lier Erlang avec d’autres langages de programmation 369 En outre, le format de terme externe d’Erlang est une représentation d’un terme Erlang sous forme d’une suite d’octets, c’est-à-dire un binaire. Les BIF term_to_binary/1 et binary_to_term/1 permettent de passer de l’un à l’autre. Nous étudierons ce format plus en détail dans la section "Programmes ports", plus loin dans ce chapitre. Nous reprendrons ici l’exemple de serveur de factorielles que nous venons d’étudier en Java, mais en l’écrivant en C en nous appuyant sur l’exemple fourni dans le "Interope rability Tutorial for Erlang" : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 /* facto.c */ #include #include #include #include <stdio.h> <sys/types.h> <sys/socket.h> <netinet/in.h> #include "erl_interface.h" #include "ei.h" #define BUFSIZE 100 int main(int argc, char **argv) { int fd; /* descripteur de fichier du nœud Erlang */ int loop = 1; /* Indicateur de boucle */ int recu; /* Résultat de receive */ unsigned char buf[BUFSIZE] /* Tampon pour message entrant */ ErlMessage emsg; /* Message entrant */ ETERM p_de, p_param, p_res; /* Repr. des termes Erlang */ int facto(int y); /* Initialisation de erl_interface (une fois seulement) */ erl_init(NULL, 0); /* Initialisation du mécanisme de connexion */ if (erl_connect_init(1, "moncookie", 0) == -1) erl_err_quit("erl_connect_init"); /* Connexion à un nœud Erlang */ if ((fd = erl_connect("truc@STC")) < 0) erl_err_quit("erl_connect"); while (loop) { /* Message reçu */ recu = erl_receive_msg(fd, buf, BUFSIZE, &emsg); if (recu == ERL_TICK) { /* ignore */ } else if (recu == ERL_ERROR) { loop = 0; } else { if (msg.type == ERL_REG_SEND) { © 2010 Pearson France – Programmer en Erlang – Francesco Cesarini, Simon Thompson Livre Erlang.indb 369 31/08/10 13:13 370 Programmer en Erlang 45 /* Extraction des champs du message */ 46 p_de = erl_element(1, emsg.msg); 47 p_param = erl_element(2, emsg.msg); 48 49 /* Appel de facto() et renvoi du résultat */ 50 p_res = erl_format("{ok, ~i}",facto(ERL_INT_VALUE(p_param))); 51 erl_send(fd, p_de, p_res); 52 53 /* Libération de la mémoire */ 54 erl_free_term(emsg.from); erl_free_term(emsg.msg); 55 erl_free_term(p_de); erl_free_term(p_param); 56 erl_free_term(p_res); 57 } } } 58 59 int facto(int y) { 60 if (y < 0) 61 return 1; 62 else 63 return y * facto(y - 1); 64 } La forme générale du code C ressemble à celle du nœud Java précédent, sauf que le code C utilise plus d’opérations de bas niveau : ■■ inclusion des fichiers en-têtes de C (lignes 3 à 6) et de l’interface Erlang (lignes 8 et 9) ; ■■ allocation de mémoire pour le tampon d’entrée (lignes 11 et 18) ; ■■ libération de la mémoire allouée aux termes Erlang (lignes 53 à 56). Les lignes 24 à 33 mettent en place le nœud et le connectent à un nœud Erlang : ■■ erl_init(NULL, 0) initialise la bibliothèque erl_interface et ne doit être appelée qu’une fois par programme. ■■ erl_connect_init(1, "moncookie", 0) initialise le mécanisme de connexion, en fixant notamment le numéro du nœud (1, ici) et le cookie utilisé. ■■ fd = erl_connect("truc@STC") se connecte au nœud Erlang truc@STC et renvoie un descripteur de fichier pour la connexion. Les lignes 35 à 57 forment une boucle sans fin qui lit un message (ligne 37) grâce à la ligne suivante : recu = erl_receive_msg(fd, buf, BUFSIZE, &emsg); Cette instruction recevra un message dans le tampon buf et le décodera pour obtenir un terme Erlang, emsg. Les messages ERL_TICK qui vérifient qu’un nœud est vivant sont ignorés (ligne 40) et la boucle se termine lorsqu’elle reçoit un message ERL_ERROR (ligne 42). Le reste de la boucle effectue le traitement suivant : © 2010 Pearson France – Programmer en Erlang – Francesco Cesarini, Simon Thompson Livre Erlang.indb 370 31/08/10 13:13 Chapitre 16 Lier Erlang avec d’autres langages de programmation 371 ■■ Extraction de l’identifiant de l’expéditeur du message, p_de, et de son contenu, p_ param (lignes 46 et 47). ■■ Conversion de p_param en entier C et passage de celui-ci en paramètre à la fonc- tion facto(), puis renvoi du terme Erlang {ok, facto(...(p_param))} au processus p_de (ligne 51). L’appel erl_format se sert d’une chaîne de format pour construire des termes Erlang lisibles. Pour construire le même terme manuellement, vous pourriez utiliser les instructions suivantes : tab[0] = erl_mk_atom("ok"); tab[1] = erl_mk_integer(facto(ERL_INT_VALUE(p_param))); = erl_mk_tuple(tab, 2); p_res ■■ Enfin, libération de la mémoire utilisée par les termes Erlang (lignes 54 à 56). Pour compiler ce programme C, indiquez les emplacements des fichiers erl_ et libei.a et précisez que vous utilisez ces bibliothèques : interface.h, liberl_interface.a gcc -o facto -I/usr/local/lib/erlang/lib/erl_interface-3.5.9/include \ -L/usr/ local/lib/erlang/lib/erl_interface-3.5.9/lib facto.c -lerl_interface -lei Dans la commande ci-dessus, les chemins mènent à la dernière version d’erl_interface sur votre système. L’exécutable produit s’appellera facto et se trouvera dans le répertoire courant. Voici maintenant le code Erlang pour se connecter au nœud C. En général, le nom du nœud C est cN, où N est le numéro d’identification du nœud. Ici, nous utilisons donc c1@STC : -module(facto). -export([call/1]). call(X) -> {any, 'c1@STC'} ! {self(), X}, receive {ok, Result} -> Result end. Son utilisation dans le shell Erlang donne le résultat suivant : % erl -sname "truc" -setcookie "moncookie" ...... L'exécutable C devrait être appelé ...... (truc@STC)1> c(facto). {ok,facto} (truc@STC)2> facto:call(7). 5040 (truc@STC)3> facto:call(0). 1 Ici, le nœud C agit comme un client : le nœud Erlang doit donc être lancé d’abord pour qu’il s’exécute déjà lorsque le nœud C tentera de s’y connecter. © 2010 Pearson France – Programmer en Erlang – Francesco Cesarini, Simon Thompson Livre Erlang.indb 371 31/08/10 13:13 372 Programmer en Erlang Pour aller plus loin Le nœud C que nous venons de décrire s’exécute comme un client : il peut se connecter à des nœuds Erlang. Il peut également s’exécuter en mode serveur – il faut alors que le programme crée d’abord une socket écoutant sur un port particulier et qu’il la publie à l’aide d’epmd. Il pourra ensuite accepter les demandes de connexion provenant de nœuds Erlang. La bibliothèque erl_interface offre de nombreuses autres possibilités, comme le pattern matching sur les messages entrants, un système de base de registres pour stocker des paires clé-valeur et un schéma de nommage global. Toutes ces fonctionnalités, ainsi que la programmation des nœuds en mode serveur, sont décrites dans l’"Interoperability Tutorial" et le guide de l’utilisateur de la bibliothèque erl_interface. Erlang à partir du shell Unix : erl_call La commande Unix erl_call fait partie des "trésors cachés d’OTP". Elle a été créée à partir d’erl_interface pour permettre de communiquer à partir du shell Unix avec un nœud Erlang distribué. Elle permet également de compiler et d’évaluer du code Erlang à partir de la ligne de commande. Son aptitude à lire sur stdin est mise à profit par d’autres scripts – ceux de CGI, notamment. L’ensemble complet des paramètres et options de cette commande est décrit dans sa page de manuel ou résumé en appelant erl_call sans aucun paramètre ou option. Les seules options obligatoires sont -n, -name ou -sname car elles permettent de préciser le nom (ou le nom court) du nœud appelé. Elles sont souvent accompagnées de l’option -s, qui lance le nœud s’il ne s’exécute pas déjà. L’option -a est l’équivalent de apply/3 et ses paramètres sont au même format, tandis que -e évalue tout ce qui est fourni sur l’entrée standard (jusqu’à Ctrl+D). Voici un exemple d’utilisation d’erl_call : % erl_call -s -a 'erlang date' -n machin {2010, 6, 12} % erl_call -s -e -n machin X=3, Y=4, X+Y. Ctrl-D {ok, 7} % erl_call -a 'erlang halt' -n machin % © 2010 Pearson France – Programmer en Erlang – Francesco Cesarini, Simon Thompson Livre Erlang.indb 372 31/08/10 13:13