4. Communication avec une application, en utilisant le protocole DDE. PrologIA HERITAGE II+
A!ociation
Prolog
HERITAGE
4. Communication avec une application, en utilisant le protocole
DDE
4.1. Aperçu du protocole DDE
4.2. Utilisation simple de Prolog II+ comme serveur DDE
4.3. Programmer en Prolog II+ un applicatif Client ou Serveur
L'environnement de Prolog II+ supporte le protocole DDE, d'une manière portable entre Windows 32 et OS/2-PM. Ces nouvelles fonctionnalités offrent deux types de possibilités:
- Lancer des buts Prolog et en récupérer les résultats depuis un applicatif Client externe, et ce, sans écrire aucun code d'interface,
- En chargeant un module Prolog spécifique, disposer d'un jeu complet de primitives permettant l'écriture en Prolog, sans aucune extension C, de tout applicatif Client ou
Serveur DDE.
4.1. Aperçu du protocole DDE
Ceci n'est qu'une présentation très rapide du protocole DDE. L'utilisateur est invité à se reporter à la documentation du système hôte choisi pour approfondissement.
Le DDE est un protocole de communication unidirectionnelle entre deux applicatifs nommés Client et Serveur, à l'initiative du Client, de manière interne à la plateforme.
© PrologIA
U 4 - 2
Manuel d'Utilisation Windows
4.1.1. Les trois niveaux d'identification du protocole DDE
Le protocole DDE est fondé sur une identification à trois niveaux d'échanges, couramment nommés "Service", "Topic" et "Item". Chaque identifiant est une chaîne de texte, en général sensible aux minuscules/majuscules, limitée à environ
255 caractères, et à priori unique dans le contexte fixé par l'identifiant du niveau précédent.
Le Service identifie un Serveur logique. En pratique, c'est le plus souvent le nom générique de l'applicatif Serveur lui-même ("EXCEL", "WORD", "CLOCK", ...).
Mais rien n'empêche un Serveur de déclarer plusieurs Services, s'il est capable de les gérer.
Le Topic indique un thème de conversation. C'est donc la base fondamentale de l'ouverture d'un échange DDE. En pratique, le Topic relève le plus souvent d'un
Serveur précis, et donc il existe entre Topic et Service un lien implicite (par exemple: qui sait éditer la "Feuille de Calcul Excel nommée EXAMPLE.XLS" ?). Mais rien n'empêche un Serveur quelconque qui en a la compétence d'accepter un Topic donné.
Le nom d'Item indique un objet "donnée" précis relatif à une conversation ouverte sur un thème donné. En pratique, il s'agit donc souvent d'un "paragraphe" précis du
"document" ouvert (par exemple: la plage "E7-K9" de la feuille de calcul précitée).
Mais ce peut être toute entité conceptuellement subordonnée au Topic, compatible avec les opérations DDE à effectuer sur elle (par exemple: un signal "Reset" accédé forcément pour une opération "Poke", dans une conversation de Topic "Time" ouverte avec "CLOCK").
Indépendamment de ces identifications, un échange DDE se caractérise par le choix d'un format de donnée. Celui-ci, public ou propriétaire, est négocié implicitement lors de l'ouverture de la conversation: le Client est supposé s'être enquis des formats supportés par le Serveur pour le Topic visé, et avoir choisi le plus riche que luimême supporte.
A!ociation
Prolog
HERITAGE
© PrologIA
A!ociation
Prolog
HERITAGE
Communication avec une application, en utilisant le protocole DDE
U 4 - 3
Client Logique
Le Formalisme DDE
TEXT seulement pour Prolog
(actuellement)
Execute( Ordre)
RequestData
HotLinkData
WarmLinkData
PokeData( Donnée)
Data pour RequestData, sinon STATUT Booléen
"Item 1"
"Item 2"
"Item z"
Serveur Logique
= son Service
"Service"
"Topic 1"
Telle Donnée
Telle Autre
Donnée
"Topic n"
4.1.2. Les possibilités du protocole DDE Prolog
Afin de respecter le modèle de programmation standard de Prolog II+, le protocole
DDE général a été adapté suivant les possibilités suivantes:
- Tous les échanges se traduisent par des appels de primitives ou bien l'appel automatique de buts par le système. Ces buts seront dans toute la suite appelés
"buts-callbacks". Le retour d'une primitive correspond à la fin d'une transaction et fournit le statut associé.
- Les paramètres des communications lui sont présentés sous une forme classique en Prolog II+: les chaînes de texte elles-mêmes pour les chaînes d'identification
(Service,Topic,Item), et un entier opaque pour les identificateurs de conversation.
Une base de données interne assure la conversion et le contrôle de cohérence des paramètres fournis par l'utilisateur.
- Les capacités du DDE Prolog sont limitées à des données de type "Chaîne de
Texte Standard".
- Le cas où ni le Service ni le TOPIC n'est spécifié par le Client potentiel suppose une phase de négociation où le Serveur décrit ce qu'il propose. Ce sous-protocole n'est pas implémentable sous forme de squelette extensible en Prolog. Donc il a
été décidé que seules les "Wild Connections" avec Topic spécifié seraient
acceptées par Prolog.
© PrologIA
U 4 - 4
Manuel d'Utilisation Windows
- Les buts-callbacks intervenant dans des mécanismes systèmes, avec les problèmes classiques que cela suppose, ne peuvent pas être mis au point "sur site" mais devront l'être avant raccordement, dans un contexte de simulation. De même, ils doivent fournir des traitements de durée "raisonnable", cette notion restant intuitive.
- La notification de la transmission d'une donnée se fait sur la base du Topic. La distribution à chaque client concerné par ce Topic est assurée de manière interne.
A!ociation
Prolog
HERITAGE
4.2. Utilisation simple de Prolog II+ comme serveur DDE
Pour utiliser Prolog II+ comme un Serveur DDE, il est nécessaire de disposer d'un applicatif Client capable de formuler des requêtes paramétrables au format
"Texte Pur". A titre de test, il existe plusieurs possibilités:
- disposer déjà d'un tel applicatif, même surdimensionné pour cet usage,
- utiliser un "Sample DDE Client" fourni avec le Software Development Kit pour la plate-forme hôte (exemple: le SDK 32 bits de MicroSoft pour Windows),
- utiliser une autre instance de Prolog II+ programmée en Client DDE.
4.2.1. Initialisation du serveur Prolog II+
Afin de valider le Service DDE, la primitive suivante doit être invoquée:
ddePublishExternalEvent( _bActivate)
Active (_bActivate vaut 1) ou désactive (_bActivate vaut 0) le Service.
La désactivation du Service interdit toute future connexion, mais ne congédie pas les Clients éventuellement déjà connectés. Cependant, ils le seront de manière correcte si Prolog II+ se termine prématurément.
Après validation, Prolog II+ publie un Service (ou nom d'application) intitulé
Prolog2 et sous lequel il reconnaît le Topic ExternalEvent. Une "Wild
Connection" sans Service mais spécifiant ce Topic sera aussi acceptée. Un nombre quelconque de Clients peuvent se connecter (chacun suivant sa méthode), jusqu'à limitation par le système.
Il est à remarquer que lors de la connexion et de toute opération ultérieure, la console de Prolog II+ ne manifeste aucune réaction, sauf pour une opération d'écriture explicite.
Après connexion, le Client peut utiliser librement les requêtes DDE standards avec la sémantique qui va être décrite ci-après.
© PrologIA
A!ociation
Prolog
HERITAGE
Communication avec une application, en utilisant le protocole DDE
U 4 - 5
4.2.2. Transmission d'une requête à Prolog II+
Il existe deux possibilités:
- Envoi d'une requête de type Poke sur un Item nommé "texte", sans donnée additionnelle (ignorée si présente): un événement de type extern_event( "texte", 0,
0) est placé dans la queue d'événements de Prolog II+, et pourra être lu par le prédicat get_event/3 du module graphique.
- Envoi d'une requête de type Execute (le paramètre Item n'existe pas), avec une donnée but_prolog: le but transmis est placé dans la queue d'exécution de
Prolog II+, et sera lancé par la machine de manière asynchrone. Le succès de la
requête traduit celui de la transmission, et non celui du but transmis. On ne considère pas ici la récupération des solutions.
Les messages d'erreur éventuels de Prolog se manifestent dans l'unité de sortie courante, par défaut la console, et ne sont pas transmis au Client. L'unification des variables du but transmis ne produit aucune trace. Seules les écritures explicites seront visibles.
Limitation: La donnée but_prolog est limitée à 32767 caractères et doit avoir la forme d'un but unique (et non pas une suite ou liste de buts) respectant la syntaxe en cours, sinon, une erreur est générée.
Exemples: réponses de la console de Prolog II+ à quelques requêtes:
- Requête Poke sur l'Item "Lily was here" avec la donnée "You won't see me":
> get_event( 0, x, y);
{ x=extern_event( "Lily was here", 0, 0), y=0 }
>
- Requête Execute avec donnée "please( "anser me")":
-> please/1 : APPEL A UNE REGLE NON DEFINIE
>
- Requête Execute avec donnée "enum( i, 15)":
>
(il ne se passe rien de visible)
- Requête Execute avec donnée "outml( "Hello )":
Hello
> ( mais pas d'affichage de {} )
© PrologIA
U 4 - 6
Manuel d'Utilisation Windows
4.2.3. Exécution d'un but Prolog avec récupération des solutions
La donnée transmise par la requête Execute accepte une seconde syntaxe dont la description suit:
but_prolog, Index, Identifiant où:
but_prolog obéit aux contraintes précédemment exposées,
Index est le numéro basé en 1 de l'argument de but_prolog à récupérer,
Identifiant a la syntaxe d'un identificateur abrégé Prolog (sans préfixe) et désignera la solution.
Lors de l'exécution du but, la valeur assignée à l'argument désigné sera convertie en une chaîne de caractères, et associée à son identifiant. Si le but échoue ou produit une erreur, la valeur assignée à la solution sera respectivement "*Failure" ou
"*Error nnn", nnn étant le code d'erreur Prolog. Le Client peut récupérer la ou les solutions de deux manières:
- Par l'envoi d'une requête Request sur l'Item Identifiant lancée après l'exécution du but: la valeur rendue est celle de la dernière solution courante du but auquel est associé l'identifiant, dans les conditions décrites précédemment.
L'inconvénient est qu'il n'existe aucun moyen de synchronisation automatique permettant de savoir si le but a été exécuté. Si ce n'est pas le cas, la requête
échoue, sauf si l'identifiant utilisé contient déjà la solution d'un autre but lancé précédemment. Le second inconvénient est que l'on récupère seulement la dernière solution.
- Par l'envoi d'une requête HotLink ou Advise sur l'Item Identifiant, lancée avant exécution du but: lors de l'exécution du but auquel est associé l'identifiant, chaque solution (au sens précédent) est transmise au Client en tant que mise à jour de l'Item. L'avantage de cette méthode est que la synchronisation est semiimplicite: elle convient très bien à un Client à structure événementielle. Il est à noter que si le Client veut différencier la dernière solution des autres, le but appelé devra être encapsulé afin de transmettre une solution différentiable. Après avoir eu satisfaction, le Client devra annuler le lien (Requête Unadvise).
Remarques:
- Si le Serveur Prolog II+ est sollicité par plusieurs Clients, les buts transmis sont empilés par ordre chronologique, sans autre lien avec leur auteur que l'identifiant spécifié. Cette caractéristique permet de partager des données entre Clients, avec ou sans leur consentement. Dans le cadre d'une application reposant sur plusieurs applicatifs, il convient de bien choisir les identifiants utilisés.
A!ociation
Prolog
HERITAGE
© PrologIA
A!ociation
Prolog
HERITAGE
Communication avec une application, en utilisant le protocole DDE
U 4 - 7
- Dans le cas où l'un des Clients transmet le but quit, ou tout autre ayant un effet de bord quelconque, Prolog II+ l'exécute sans considération pour les intérêts des autres Clients. Exemple: un outil tentant périodiquement une connexion sur
Prolog II+ pour y lancer une requête Execute( quit) constituerait un vrai vaccin anti-Prolog.
4.2.4. Schéma du Serveur Prolog II+
Ce schéma est à rapprocher de celui plus général donné précédemment:
Client Logique
Le Service DDE "PROLOG"
Serveur Logique:
Service Automatique
"Prolog2"
Conversation Unidirectionnelle (TEXT)
"ExternalEvent"
Execute( "But, Arg, Numéro")
RequestData
"Der. Solution N°"
HotLinkData
"Toute Solution N°"
PokeData()
"N'importe Quoi"
Data pour RequestData, sinon STATUT Booléen
Queue des Buts
Execution
Queue d'Evénements
get_event()
4.2.5. Exemples
- La requête Execute avec la donnée 'eq(production, x), 2, my_var' réussit et associe dans l'interface la valeur de x (ici production) à l'identifiant my_var.
- La requête Execute avec la donnée 'eq(production, x), 1, my_atom' réussit.
- La requête Request pour l'item my_var réussit et rend production
© PrologIA
U 4 - 8
Manuel d'Utilisation Windows
- La requête Request pour l'item my_atom' réussit et rend production (1er argument).
- La requête Execute avec la donnée 'arg2( X, Y, Z), 3, my_arg' réussit, mais le message:
-> <v33> : ARGUMENT DE MAUVAIS TYPE
est affiché dans la console de Prolog II+
- La requête Request pour l'item my_arg réussit et rend *Error 253
- La requête Advise (ou HotLinkData) pour l'item enumerate réussit.
- La requête Execute avec donnée 'enum( i, 5), 1, enumerate ' réussit, et le Client reçoit successivement: 1, 2, 3, 4, 5.
- La requête Request pour l'item enumerate réussit et rend 5.
A!ociation
Prolog
HERITAGE
4.3. Programmer en Prolog II+ un applicatif Client ou Serveur
Il est nécessaire dans les deux cas de charger le module "dde.mo" qui installe les primitives DDE. Sa désinstallation se fait par l'appel à la primitive:
ddeCleanup/0
Termine toutes les conversations et Services en cours et élimine les primitives de Prolog relatives au DDE. Cette primitive n'est pas le bon moyen pour un applicatif Client ou Serveur de terminer son activité DDE. Elle ne devrait être utilisée qu'ensuite.
Selon les performances du système et des applicatifs, des problèmes de time-out peuvent survenir, produisant une erreur Prolog. Le délai général de time-out, bien que confortable (3 secondes) peut être ajusté par l'option -M tttt de la ligne de commande, où tttt est la durée en millisecondes. Cette valeur sera à déterminer par essais. Elle est talonnée par les valeurs 200 et 15000 ms.
Les paragraphes qui suivent étudient séparément les deux modes, mais rien n'interdit
à un applicatif d'être simultanément Client et Serveur pour des conversations différentes. Il convient alors en l'écrivant d'accorder le plus grand soin à la gestion des numéros de conversations et éventuellement aux identificateurs DDE utilisés.
Pour cela, la primitive suivante sera un auxilliaire précieux:
ddeRememberDatabase( _xData)
Enumère les Services et les conversations en cours et les unifie avec l'argument _xData. Son format est le suivant:
dde_I_serve(_tService) pour les Services (seulement pour le Serveur donc),
dde_I_am_Client(_hConversation, _tTopic) ou
dde_I_am_Server(_hConversation, _tTopic,) (selon le cas) pour les conversations.
© PrologIA
A!ociation
Prolog
HERITAGE
Communication avec une application, en utilisant le protocole DDE
U 4 - 9
4.3.1. Programmer un applicatif Client DDE
Les transactions DDE sont à l'initiative du Client, mais certaines prennent aussi la forme de notifications asynchrones de la part du Serveur. Le Client est supposé en tenir compte pour adapter sa conduite. De même, le Client est supposé connaître le mode d'emploi du Serveur qu'il prétend utiliser. Eventuellement, il y aura également lieu pour le Client de démarrer l'applicatif Serveur désiré.
Primitives de connexion et de déconnexion
ddeDeclareAsClient( _xService, _tTopic, _hConversation)
Tente d'ouvrir une conversation sur le Topic spécifié par la chaîne de caractères _tTopic avec le Serveur logique spécifié par la chaîne de caractères
_xService, ou n'importe quel serveur si _xService vaut nil. Si la conversation est ouverte, l'argument _hConversation est unifié avec une valeur (entier opaque) unique identifiant cette conversation pour toute opération future. Si aucun serveur n'est trouvé, une erreur est signalée. Si plusieurs serveurs sont candidats, seule la première réponse sera retenue.
ddeEndConversation( _hConversation)
Termine la conversation désignée par _hConversation en congédiant le
Serveur. Si _hConversation est une variable libre, termine par énumération
(backtracking) toutes les conversations en cours en unifiant _hConversation avec la conversation concernée. Si la conversation désignée n'existe pas, l'unification échoue. L'usage de cette primitive est naturel pour le Client.
Primitive de transmission de requêtes
ddeTransmitRequest( _hConversation, _xRequest)
Effectue de manière synchrone la requête _xRequest auprès du Serveur lié à la conversation _hConversation. Le statut de terminaison de cette primitive
(succès ou erreur) est lié à celui de la requête. Les requêtes reconnues sont les suivantes:
- ddeRequestData(_tItem, _xValue): effectue une requête Request standard pour la donnée nommée par la chaîne _tItem, et tente d'unifier le résultat, une chaîne de texte Prolog, avec la valeur de _xValue.
- ddeWarmLinkData(_tItem, ddeOpen) ou
ddeWarmLinkData(_tItem, ddeClose): effectue une requête Advise standard pour la donnée nommée par la chaîne _tItem, demandant un abonnement de type notification de modification de cette donnée (lien tiède), ou résilie ce même abonnement.
- ddeHotLinkData(_tItem, ddeOpen) ou
ddeHotLinkData(_tItem, ddeClose): effectue une requête Advise standard pour la donnée nommée par la chaîne _tItem, demandant un abonnement de type mise à jour systématique de cette donnée (lien chaud), ou résilie ce même abonnement.
© PrologIA
U 4 - 10
Manuel d'Utilisation Windows
- ddePokeData(_tItem, _xData): effectue une requête Poke standard pour l'Item nommé par la chaîne _tItem, adressant ainsi au Serveur la donnée
_xData, qui est soit une chaîne de texte, soit nil (simple signal sans donnée jointe).
- ddeExecute(_xArgument): effectue une requête Execute standard au Serveur, lui passant une commande textuelle contenue dans la chaîne _xArgument.
Buts-callbacks
Les buts-callbacks (noms prédéfinis) sont dans le module global (ils ont le préfixe
""). Ils sont écrits par l'utilisateur et appelés par le système. Ils sont donc soumis à des contraintes relevant de la programmation système. On retiendra principalement les règles suivantes:
- Les buts-callbacks peuvent effectuer des retours arrière, mais la requète transmise sera validée (si toutefois la requête attend une validation) s'il existe au moins une solution.
- Les buts-callbacks ne doivent pas effectuer de traitements de taille déraisonnable
(notion purement intuitive), ni à fortiori d'intèraction avec l'utilisateur incluant des phases modales. Il y a risque de time-out, voire même de réaction défensive du système.
- Ceci implique que les buts-callbacks ne peuvent pas être mis au point sur site. Il est nécessaire d'effectuer leur mise au point avec un simulateur.
:ddeCbServerClosing( _hConversation)
Signale la terminaison prématurée de la conversation _hConversation par le
Serveur, quelle qu'en soit la raison. Il s'agit d'une notification à postériori, et le statut de terminaison de son traitement est sans effet sur le résultat transmis au serveur. La valeur de _hConversation doit être considérée comme désormais invalide et recyclable (donc ddeEndConversation( _hConversation) échouera si tenté).
:ddeCbServerUpdate( _hConversation, _tItem, _xArgument)
A la suite d'une requête Advise, notifie un changement dans la valeur de l'Item auquel le Client s'est abonné pour la conversation _hConversation. Cet Item est désigné par la chaîne de caractères _tItem. La nouvelle valeur est soit transmise dans _xArgument (lien chaud) soit disponible pour une future requête de type ddeRequestData (lien tiède). Dans ce dernier cas, _xArgument vaut nil. Le statut de terminaison de ce but n'a aucun sens ni aucun effet sur le résultat transmis au serveur.
Exemple
Le scénario suivant décrit, en Prolog, un dialogue avec un Serveur de type horloge.
> load( "dde.mo") ;
{}
> insert; % Code minimum nécessaire pour suivre le dialogue
A!ociation
Prolog
HERITAGE
© PrologIA
A!ociation
Prolog
HERITAGE
Communication avec une application, en utilisant le protocole DDE
U 4 - 11
ddeCbServerUpdate( _hC, "Now", "24:00:00") -> ddeTransmitRequest( _hC, ddeExecute("Close") )
! ; ddeCbServerUpdate( _, "Now", _tTime) -> outm( "\tIt is ") outml( _tTime) ; ddeCbServerClosing( _) -> outml( "\t\tEnd !") ;
;
{}
> ddeDeclareAsClient( nil, "Time", _hC);
{ _hC=1 }
> ddeTransmitRequest( 1, ddeRequestData("Now", _t));
{ _t="15:20:33" }
> ddeTransmitRequest( 1, ddePokeData("Now", "23:59:30"));
{}
> ddeTransmitRequest( 1, ddeHotLinkData("Now", ddeOpen));
{}
It is 23:59:55
It is 23:59:56
It is 23:59:57
It is 23:59:58
It is 23:59:59
End !
> ddeEndConversation( 1); % Failure, number 1 is out-of date
>
4.3.2. Programmer un applicatif Serveur DDE
Ce mode est plus contraignant, car un Serveur doit savoir être à la complète disposition de Clients quelconques, et aussi éviter tout conflit d'intérêts avec d'autres
Serveurs. Donc il importe en premier lieu de définir formellement puis de doter de noms pertinents toutes les commandes qu'il pourra recevoir. Son mode d'emploi devra être très complet.
Primitive de déclaration
ddeDeclareAsServer( <_nMode, _tService>)
Déclare (si _nMode vaut ddeOpen ) ou supprime (si _nMode vaut ddeClose) le Service DDE nommé par la chaîne de caractères _tService. Si _tService est une variable libre et _nMode vaut ddeClose, termine chaque Service déclaré
(backtracking) en l'unifiant avec _tService. La suppression d'un Service renvoie brutalement tous les Clients qui s'y sont connectés. Ceci devrait être
évité, en terminant au préalable toutes les conversations concernées.
Primitives de connexion et de déconnexion
ddeAcceptClient( _tService, _tTopic, _hConversation)
Accepte la requête du Client en cours de connexion, cette primitive devant être invoquée durant l'effacement du but-callback ddeCbClientWantsServer/2. Les arguments _tService et _tTopic sont des chaînes de caractères transmises par ce but-callback. Si aucun problème système ne survient, l'argument
_hConversation sera unifié avec une valeur entière unique identifiant cette conversation pour toute opération future.
© PrologIA
U 4 - 12
Manuel d'Utilisation Windows ddeEndConversation( _hConversation)
Termine la conversation _hConversation en congédiant le Client. Si
_hConversation est une variable libre, termine par énumération toutes les conversations en cours en unifiant _hConversation avec la conversation concernée. L'usage de cette primitive est naturel pour le Client. Bien que possible, l'usage de cette primitive est à priori très déplacé pour le Serveur. Il ne devrait être utile qu'en cas de problème.
Primitive de transmission des données aux Clients:
ddeTransmitData( _tTopic, _tItem, _xNewValue)
- Doit être invoquée à la demande d'un Client, donc durant l'effacement du but-callback ddeCbClientRequest/2 pour une requête ddeRequestData, pour transmettre _xNewValue, la nouvelle valeur de l'Item _tItem.
- Peut être invoquée à l'initiative du Serveur pour transmettre soit la nouvelle valeur _xNewValue de l'Item _tItem (lien chaud) soit une notification aux
Clients ayant demandé un abonnement à l'Item modifié (lien tiède), auquel cas l'argument _xNewValue est ignoré. Le choix de notifier sur la base du Topic
_tTopic et non à chaque Client concerné est imposé par des contraintes d'implémentation. La base de données interne assure la bonne distribution des notifications.
Buts-callbacks
Mêmes remarques que pour le mode Client.
:ddeCbClientWantsServer( _xService, _tTopic)
Notifie une demande de connexion d'un Client pour le Topic désigné par la chaîne de caractères _tTopic et au Serveur logique désigné par la chaîne de caractères _xService, sauf si _xService vaut nil, ce qui signifie "sans préférence". Pour que la conversation soit établie, le Serveur doit effacer ce but et durant cette opération effacer la primitive ddeAcceptClient/3, sans quoi
(erreur ou échec) le Client est débouté. A priori, le Client n'est pas tenu d'insister, et donc un refus du Serveur peut être considéré comme définitif.
:ddeCbClientRequest( _hConversation, _xRequest)
Notifie la requête _xRequest du Client, dans les conditions liées à la conversation _hConversation, et attend la réponse de manière synchrone. Le statut de terminaison de ce but conditionne celui de la requête. Une erreur
Prolog aura ici le même effet qu'un échec. Les requêtes reconnues sont les suivantes:
- ddeRequestData(_xArgument): notifie une requête Request standard pour la donnée nommée par la chaîne _xArgument, et attend du Serveur l'exécution de la primitive ddeTransmitData/3 passant sa nouvelle valeur durant l'effacement du but,
- ddeWarmLinkData(_tItem, ddeOpen) ou
A!ociation
Prolog
HERITAGE
© PrologIA
A!ociation
Prolog
HERITAGE
Communication avec une application, en utilisant le protocole DDE
U 4 - 13
ddeWarmLinkData(_tItem, ddeClose): notifie une requête Advise standard pour la donnée nommée par la chaîne _tItem, demandant un abonnement de type notification à cette donnée (lien tiède), ou la résiliation de ce même abonnement, information que le Serveur est supposé enregistrer pour adapter son comportement futur,
- ddeHotLinkData(_tItem, ddeOpen) ou
ddeHotLinkData(_tItem, ddeClose): notifie une requête Advise standard pour la donnée nommée par la chaîne _tItem, demandant un abonnement de type mise à jour systématique à cette donnée (lien chaud), ou la résiliation de ce même abonnement, information que le Serveur est supposé enregistrer pour adapter son comportement futur,
- ddePokeData(_tItem, _xValue): notifie une requête Poke standard pour l'Item nommé par la chaîne _tItem, adressant ainsi la donnée _xValue (chaîne de texte Prolog) au Serveur, ou bien encore un simple signal sans donnée jointe, _xValue valant alors nil,
- ddeExecute(_xArgument): notifie une requête Execute standard au Serveur, lui passant une commande textuelle préconvenue contenue dans la chaîne
_xArgument, que le Serveur est supposé comprendre et exécuter de manière synchrone, et dont le statut doit conditionner le succès de ce but,
- ddeClose: notifie la déconnexion du Client. La base de donnée interne est mise à jour automatiquement, et le Serveur est supposé faire de même pour ses données propres éventuelles. Il s'agit d'une notification à postériori, et le statut de terminaison du but est sans effet.
Exemple
Imaginons un Serveur représentant le garde-manger d'un restaurant. Il doit gérer le stock de différents plats, consommés de manière aléatoire. Il doit pour chacun pouvoir donner la quantité disponible et retrancher la quantité consommée. Il doit alerter le patron en cas de rupture de stock et ensuite pouvoir lister sur commande les plats à renouveler. Enfin, il doit pouvoir enregistrer une livraison.
On définit le nom du Service: Fridge.
On définit les noms des Topics: Boss, réservé au maître unique des lieux,
Waiter, pour les serveurs de la salle.
Les Items seront les noms des plats, associés à une quantité disponible dans une base de données interne. Un Item nommé "Rupture" et accessible au seul patron lui permet de connaître la liste des plats dont le stock est inférieur à 5. Le patron peut l'interroger par Request et/ou s'y abonner. Il recevra alors la liste à jour à chaque consommation d'un serveur de la salle. Seul le patron est autorisé à alimenter le
Frigo par une requête Execute passant une liste chiffrée. Il a aussi accès à toutes les opérations permises aux serveurs de la salle.
© PrologIA
U 4 - 14
Manuel d'Utilisation Windows
Le code de cet exemple est donné dans le fichier ddefrigo.p2 du kit. On remarque qu'il est nettement plus volumineux que le précédent. Pour l'utiliser de manière amusante, il est préférable de disposer de plusieurs (environ 3) applicatifs Clients pouvant utiliser (facilement) des Identifiants DDE arbitraires. pour le cas où des instances de Prolog sont utilisées comme clients, un fichier nommé ddecligo.p2, disponible dans le kit fournit des commandes simplifiées adaptées à cet exemple.
Dans tous les cas, lancer la règle to_begin pour démarrer ces programmes. Ils listent alors leur mode d'emploi.
Les manipulations suivantes sont suggérées:
- En premier, remplir le garde-manger, initialement vide: le patron lance par exemple une requête Execute de la chaîne: "4 Lapin, 15 Poulet, 7 Gateau Basque, end" ,
- Essayer de connecter un second patron, surtout si le premier est déjà abonné à
Rupture,
- Essayer de réclamer un plat indisponible: Requête Poke de "nom du plat, -1" par exemple,
- Vérifier que le patron est prévenu lorsque les stocks diminuent,
- ...
A!ociation
Prolog
HERITAGE
© PrologIA

公開リンクが更新されました
あなたのチャットの公開リンクが更新されました。