Lier Erlang avec d autres langages de programmation



Documents pareils
Programmer en JAVA. par Tama

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

TP1. Outils Java Eléments de correction

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

Programmation système de commandes en C

Cours 1 : Introduction. Langages objets. but du module. contrôle des connaissances. Pourquoi Java? présentation du module. Présentation de Java

as Architecture des Systèmes d Information

Introduction au langage C

Cours 1 : La compilation

Algorithmique et Programmation, IMA

Programmation C. Apprendre à développer des programmes simples dans le langage C

Programmation Web. Madalina Croitoru IUT Montpellier

Premiers Pas en Programmation Objet : les Classes et les Objets

Corrigé des exercices sur les références

Bases Java - Eclipse / Netbeans

RAPPORT DE CONCEPTION UML :

Programmation en Java IUT GEII (MC-II1) 1

Remote Method Invocation (RMI)

TD3: tableaux avancées, première classe et chaînes

Une introduction à Java

Plan du cours. Historique du langage Nouveautés de Java 7

Programmation système I Les entrées/sorties

Solutions du chapitre 4

TP1 : Initiation à Java et Eclipse

Le langage C. Séance n 4

RMI. Remote Method Invocation: permet d'invoquer des méthodes d'objets distants.

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

Java Licence Professionnelle CISII,

RMI le langage Java XII-1 JMF

La base de données XML exist. A. Belaïd

TP 1. Prise en main du langage Python

Machines virtuelles. Brique ASC. Samuel Tardieu Samuel Tardieu (ENST) Machines virtuelles 1 / 40

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Cours 1 : Qu est-ce que la programmation?

OS Réseaux et Programmation Système - C5

Conventions d écriture et outils de mise au point

3IS - Système d'exploitation linux - Programmation système

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

UE Programmation Impérative Licence 2ème Année

Introduction à la programmation concurrente

STS SE. FreeRTOS. Programmation réseau WIFI. Programmation réseau. Socket Tcp. FlyPort smart Wi-Fi module

Java DataBaseConnectivity

L informatique en BCPST

Remote Method Invocation Les classes implémentant Serializable

Licence Sciences et Technologies Examen janvier 2010

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

Utilisation d objets : String et ArrayList

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

Langage et Concepts de ProgrammationOrientée-Objet 1 / 40

SHERLOCK 7. Version du 01/09/09 JAVASCRIPT 1.5

ARDUINO DOSSIER RESSOURCE POUR LA CLASSE

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Cours 1: Java et les objets

Exceptions. 1 Entrées/sorties. Objectif. Manipuler les exceptions ;

DUT Informatique Module Système S4 C Département Informatique 2009 / Travaux Pratiques n o 5 : Sockets Stream

Tp 1 correction. Structures de données (IF2)

Utiliser Java sans BlueJ

Le modèle client-serveur

Programmation Internet en Java

Java Licence Professionnelle CISII,

Windows Internet Name Service (WINS)

Introduction à MATLAB R

CCNA Discovery Travailler dans une PME ou chez un fournisseur de services Internet

Serveur d'archivage 2007 Installation et utilisation de la BD exist

Derrière toi Une machine virtuelle!

Travaux pratiques. Compression en codage de Huffman Organisation d un projet de programmation

TP : Gestion d une image au format PGM

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

Évaluation et implémentation des langages

Atelier Le gestionnaire de fichier

INF 321 : mémento de la syntaxe de Java

RAPPELS SUR LES METHODES HERITEES DE LA CLASSE RACINE Object ET LEUR SPECIALISATION (i.e. REDEFINITION)

Introduction à la Programmation Parallèle: MPI

Installation d un serveur HTTP (Hypertext Transfer Protocol) sous Débian 6

Programmation Réseau SSH et TLS (aka SSL)

Pour plus de détails concernant le protocole TCP conférez vous à la présentation des protocoles Internet enseignée pendant.

Environnements de développement (intégrés)

Chapitre 1 Qu est-ce qu une expression régulière?

ACTIVITÉ DE PROGRAMMATION

Présentation du langage et premières fonctions

Traitement de données

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Cours d Algorithmique et de Langage C v 3.0

DE L ALGORITHME AU PROGRAMME INTRO AU LANGAGE C 51

TP, première séquence d exercices.

Chapitre 10. Les interfaces Comparable et Comparator 1

Utilisation de JAVA coté Application serveur couplé avec Oracle Forms Hafed Benteftifa Novembre 2008

2. MAQUETTAGE DES SOLUTIONS CONSTRUCTIVES. 2.2 Architecture fonctionnelle d un système communicant.

Cours d initiation à la programmation en C++ Johann Cuenin

Généralités sur le Langage Java et éléments syntaxiques.

Tutoriel: Création d'un Web service en C++ avec WebContentC++Framework

Allocation de l adressage IP à l aide du protocole DHCP.doc

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

Sommaire Introduction... 3 Le but du projet... 3 Les moyens utilisés... 3 Informations sur le client FTP... 4 Pourquoi une version Linux et

API04 Contribution. Apache Hadoop: Présentation et application dans le domaine des Data Warehouses. Introduction. Architecture

Machines virtuelles Cours 1 : Introduction

Hébergement de sites Web

Transcription:

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 Erlang 1. 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.

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.

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");

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);

Chapitre 16 Lier Erlang avec d autres langages de programmation 365 où la variable Java pid correspond à la variable Erlang Pid, et tuple 2 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.

366 Programmer en Erlang 14 BigInteger n; 15 OtpErlangAtom ok = new OtpErlangAtom("ok"); 16 17 while(true) try { 18 o = mbox.receive(); 19 msg = (OtpErlangTuple)o; 20 de = (OtpErlangPid)(msg.elementAt(0)); 21 n = ((OtpErlangLong (msg.elementat(1))).bigintegervalue(); 22 OtpErlangObject[] reponse = new OtpErlangObject[2]; 23 reponse[0] = ok; 24 reponse[1] = new OtpErlangLong(Facto.facto(n)); 25 OtpErlangTuple tuple = new OtpErlangTuple(reponse); 26 mbox.send(de,tuple); 27 28 }catch(otperlangexit e) {break; } 29 } 30 } 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.

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 epmd (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 -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.

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 automatiquement. 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, exactement 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 format 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é.

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 "Interoperability Tutorial for Erlang" : 1 /* facto.c */ 2 3 #include <stdio.h> 4 #include <sys/types.h> 5 #include <sys/socket.h> 6 #include <netinet/in.h> 7 8 #include "erl_interface.h" 9 #include "ei.h" 10 11 #define BUFSIZE 100 12 13 int main(int argc, char **argv) { 14 int fd; /* descripteur de fichier du nœud Erlang */ 15 16 int loop = 1; /* Indicateur de boucle */ 17 int recu; /* Résultat de receive */ 18 unsigned char buf[bufsize] /* Tampon pour message entrant */ 19 ErlMessage emsg; /* Message entrant */ 20 21 ETERM p_de, p_param, p_res; /* Repr. des termes Erlang */ 22 int facto(int y); 23 24 /* Initialisation de erl_interface (une fois seulement) */ 25 erl_init(null, 0); 26 27 /* Initialisation du mécanisme de connexion */ 28 if (erl_connect_init(1, "moncookie", 0) == -1) 29 erl_err_quit("erl_connect_init"); 30 31 /* Connexion à un nœud Erlang */ 32 if ((fd = erl_connect("truc@stc")) < 0) 33 erl_err_quit("erl_connect"); 34 35 while (loop) { 36 /* Message reçu */ 37 recu = erl_receive_msg(fd, buf, BUFSIZE, &emsg); 38 39 if (recu == ERL_TICK) { 40 /* ignore */ 41 } else if (recu == ERL_ERROR) { 42 loop = 0; 43 } else { 44 if (msg.type == ERL_REG_SEND) {

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 :

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 fonction 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))); p_res = erl_mk_tuple(tab, 2); 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_ interface.h, liberl_interface.a et libei.a et précisez que vous utilisez ces bibliothèques : 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.

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 %