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 p­ourriez 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

Documents pareils