Interface graphique en Prolog avec XPCE


précédentsommairesuivant

V. Interfaçage de Prolog avec d'autres langages, exemple en C.

On peut interfacer Prolog avec Java ou C, tout en gardant le moteur IA de Prolog. Une bibliothèque JPL, est proposée par SWI-Prolog pour l'interfaçage avec Java.
Nous développerons ici une liaison avec C++ à l'aide d'une Dll d'appel à SWI-Prolog écrite en C. Le programme est écrit avec Visual C6. Cet exemple a été testé sous Windows XP Pro, pack 2 et l'IHM est téléchargeable ici.
On reprend le programme Prolog de calcul da la valeur d'une expression arithmétique, (calcul qui n'est pas simple à programmer en C !).
L' IHM écrit en C++ permet de saisir cette expression, à l'aide d'une dll écrite en C, le programme appelle Prolog pour le calcul de l'expression, et ensuite le résultat du calcul est affiché.

V-A. Code Prolog.

Le code Prolog est uniquement celui de l'appel au calcul et est contenu dans un fichier source Prolog appelé calcule.pl.

Prolog
Sélectionnez
calcule(Atom, A) :-
        term_to_atom(Expr, Atom),
        A is Expr.

V-B. Code C de la Dll d'appel à Prolog.

Le code de la dll, de nom calcule.dll, pour appeler Prolog est contenu dans le fichier calcule.c.
Ce source est inspiré de la présentation de l'interfaçage Prolog/C de la documentation de SWI-Prolog.

C
Sélectionnez
#include <stdio.h>
#include <SWI-Prolog.h>

#define MAXLINE 1024

/* Enumération de quelques types Prolog */
typedef enum {T_NIL, T_ATOM, T_INT, T_DOUBLE, T_STRING, T_LIST, T_COMPOUND, T_UNKNOWN } Pl_Type;

Pl_Type Pl_GetType(term_t u)
{
     /* Fonctions de test du type du terme Prolog u */
	if (PL_is_atom(u))
		return T_ATOM;

	if (PL_is_string(u))
		return T_STRING;

	if (PL_is_integer(u))
		return T_INT;

     /* Petite particularité les float au sens Prolog sont des
      * doubles au sens C 
      */
	if (PL_is_float(u))
		return T_DOUBLE;

	if (PL_is_list(u))
		return T_LIST;

	if (PL_is_compound(u))
		return T_COMPOUND;

	return T_UNKNOWN;
}
  /* Une des méthodes pour initialiser Prolog, est de lui passer le nom du 
   * programme appelant
   */
__declspec(dllexport) void Init_Prolog(char *prog)
{
	char *plav[2];

	plav[0] = prog;
	plav[1] = NULL;

	/* initialise Prolog , si cette initialisation échoue
     * on sort avec le code d'erreur 1
     */
	if ( !PL_initialise(1, plav) )
		PL_halt(1);
}
  /* On passe à la fonction d'appel deux chaînes in et out
   * in pour les données d'entrée
   * out pour les données de sortie, out est supposée assez longue
   */
__declspec(dllexport) void Appel_Prolog(char *in, char *out)
{ 
	char expression[MAXLINE] = {0};
    /* le predicat appelé est dans le fichier Prolog calcule.pl 
     * passé en argument de la ligne de commande du compilateur plld
     */
	predicate_t pred = PL_predicate("calcule", 2, "user");
	term_t h0 = PL_new_term_refs(2);
	int ival, rval;
	double fval;

	strcpy(expression, in);	
	PL_put_atom_chars(h0, expression);
	rval = PL_call_predicate(NULL, PL_Q_NORMAL, pred, h0);

	switch(Pl_GetType(h0+1))
	{
 	case T_INT	  : 
			PL_get_integer(h0+1, &ival);
			sprintf(out, "%d", ival);
			break;
		case T_ DOUBLE : 
			PL_get_float(h0+1, &#38;fval);
			sprintf(out, "%lf", fval);
			break;
		default		     : 
			strcpy(out, "Problème de calcul");
			break;
	}
}

__declspec(dllexport) void Fin_Prolog(void)
{
    /* Fonction inverse de PL_initialise */
	PL_cleanup(0);
}

Nous ne développerons pas ici les différents détails d'implémentation, les renseignements sur les différentes fonctions de préfixe PL_ peuvent être trouvés à cette adresse.
Pour compiler ce source, dans un premier temps et pour éviter les problèmes d'accès aux répertoires, il vaut mieux mettre les fichiers calcule.c et calcule.pl dans le répertoire /Program Files/pl/bin.
La compilation a lieu avec la commande

Console
Sélectionnez
plld -dll  -o calcule.dll calcule.c calcule.pl.

Le compilateur plld est fourni avec SWI-Prolog.

V-C. Code C++ de l'IHM.

Il a été créé une application Visual C6 « dialogbased » utilisant MFC.
Toujours pour des problèmes de chemin d'accès, il est préférable de lancer le programme dans le répertoire/Program Files/pl/bin.
Un exemple de résultat est :

Image non disponible

Le seul code intéressant est l'interaction avec Prolog, faite dans le fichier calculedlg.cpp.

V-C-1. Déclaration des types de fonctions et des fonctions.

C
Sélectionnez
typedef void T_Init_Prolog(char *);
typedef void T_Appel_Prolog(char *, char *);
typedef void T_Fin_Prolog(void);

T_Init_Prolog *Init_Prolog;
T_Appel_Prolog *Appel_Prolog;
T_Fin_Prolog *Fin_Prolog;

V-C-2. Appel de la Dll et initalisation de Prolog.

C++
Sélectionnez
BOOL CCalculeDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	/* Set the icon for this dialog.  The framework does this automatically */
	/*  when the application's main window is not a dialog */
	SetIcon(m_hIcon, TRUE);			/* Set big icon */
	SetIcon(m_hIcon, FALSE);		/* Set small icon */
	
	/* TODO: Add extra initialization here */
    /* Chargement de la Dll appelant Prolog */
	hdl = LoadLibrary("D:/Program Files/pl/bin/calcule.dll");
	if (hdl != NULL)
	{
		Init_Prolog = (T_Init_Prolog *)GetProcAddress(hdl, "Init_Prolog");
		Appel_Prolog = (T_Appel_Prolog *)GetProcAddress(hdl, "Appel_Prolog");
		Fin_Prolog = (T_Fin_Prolog *)GetProcAddress(hdl, "Fin_Prolog");
		if (Init_Prolog == NULL || Appel_Prolog == NULL || Fin_Prolog == NULL)
		{
			AfxMessageBox("Chargement des fonctions de la dll incorrect");
			EndDialog(1);
		}
		/* Ici IL FAUT initaliser Prolog avec le nom de l'exécutable qui 
		 * lance Prolog (ici c'est la Dll calcule.dll, donc on met "calcule.dll" ou "calcule"
		 */
		Init_Prolog("calcule");
	}
	else
	{
		AfxMessageBox("Chargement de la dll incorrect");
		EndDialog(1);
	}
	
    /* Autres initalisations */
	
	return TRUE;  /* return TRUE  unless you set the focus to a control */
}

V-C-3. Appel du prédicat de calcul Prolog.

C++
Sélectionnez
void CCalculeDlg::OnOK() 
{
	/* TODO: Add extra validation here*/
	char in[256], out[256];
	GetDlgItemText(IDC_EDIT1, in, 256);
	Appel_Prolog(in, out);
	SetDlgItemText(IDC_STATIC2, CString(in) +  CString(" = ") + CString(out));
}

Cet interfaçage avec le C++ est relativement simple à réaliser mais il n'est pas portable. Il faut le refaire à chaque que l'on change d'environnement de développement alors que le code Prolog reste identique. Le code complet de l'IHM est téléchargeable ici.


précédentsommairesuivant

Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.