Legatura se poate face in mod dinamic sau in mod static. In cazul legarii dinamice, extensiile C (care sunt interpretate ca niste predicate PROLOG) sunt compilate intr-o biblioteca dinamica (fisier .so), care poate fi incarcata cu ajutorul predicatului predefinit:
load_foreign_library( Fisier_so )
In cazul legarii statice, sursele C si Prolog sunt compilate impreuna cu comanda 'plld'pentru a genera un executabil.
Tipurile C corespondente celor din Prolog sunt definite in "SWI-Prolog.h". Cele mai importante sunt 'term_t', 'atom_t' si 'functor_t'. Aceste tipuri sunt de fapt referinte la structuri opace folosite in Prolog.
Aceste referinte se creeaza prin urmatoarele functii:
term_t PL_new_term_ref();
atom_t PL_new_atom(char*);
functor_t PL_new_functor(atom_t name, int arity);
Pentru crearea termenilor sunt prevazute functiile 'PL_put_...':
void PL_put_atom(term_t t, atom_t a);
void PL_put_integer(term_t t, long i);
void PL_put_float(term_t t, double f);
void PL_cons_functor(term_t h, functor_t f,
... /* args */);
void PL_cons_list(term_t list, term_t head,
term_t tail);
void PL_put_nil(term_t list);
Tipul unui termen se poate obtine cu:
int PL_term_type(term_t);
/* returneaza: PL_VARIABLE
PL_ATOM PL_STRING PL_INTEGER PL_FLOAT PL_TERM */
Valoarea unui termen se obtine cu ajutorul functiilor:
int PL_get_atom(term_t t, atom_t *a);
int PL_get_atom_chars(term_t t, char **s);
int PL_get_integer(term_t t, int *i);
int PL_get_float(term_t t, double *f);
int PL_get_functor(term_t t, functor_t *f);
int PL_get_arg(int index, term_t t, term_t a);
int PL_get_list(term_t list, term_t head, term_t
tail);
/* returneaza TRUE daca
corespunde tipul */
char* PL_atom_chars(atom_t);
atom_t PL_functor_name(functor_t f);
int PL_functor_arity(functor_t f);
Unificarea termenilor se face prin:
int PL_unify(term_t t1, term_t t2);
int PL_unify_atom(term_t t, atom_t a);
int PL_unify_atom_chars(term_t t, const char
*chars);
int PL_unify_integer(term_t t, long n);
int PL_unify_float(term_t t, double f);
int PL_unify_functor(term_t t, functor_t f);
int PL_unify_arg(int index, term_t t, term_t
a);
int PL_unify_list(term_t list, term_t head,
term_t tail);
int PL_unify_nil(term_t list);
Din limbajul C, predicatele PROLOG pot fi apelate cu:
int PL_call(term_t goal, module_t m);
/* al doilea argument
deobicei este NULL */
Invers, pentru ca functii scrise in C sa fie apelabile in Prolog, ele trebuie sa fie 'inregistrate'.
Daca utilizam modul de legare dinamica, atunci biblioteca .so (scrisa in C) trebuie sa contina o functie 'install_t install()' care este formata din apeluri la functia:
int PL_register_foreign(name, arity, function, flags);
In modul static, aceasta este rezolvata printr-un apel la functia:
void PL_register_extensions(PL_extension *e);
unde argumentul are forma:
PL_extension e[] =
{
/*{ "name", arity,
function, PL_FA_<flags> },*/
{ NULL, 0, NULL,
0 } /* terminating line */
};
O functie C apelabila in Prolog trebuie sa aiba tipul 'foreign_t', avand numarul de argumente egal cu aritatea declarata. Daca functia este nedeterminista (in flags este setat PL_FA_NONDETERMINISTIC), atunci ea mai are un ultim argument in plus, 'foreign_t handle', care poate avea valorile: PL_FIRST_CALL, PL_REDO si PL_CUTTED.
Revenirea din functie se face prin 'PL_succedd()', 'PL_fail()',
sau (in plus pentru o functie nedeterminista) 'PL_retry_address(void
* context)'. Contextul
salvat (daca este posibila revenirea la o noua solutie) se restaureaza
la un apel PL_REDO cu ajutorul functiei:
void * PL_foreign_context_address(control_t handle)
Un exemplu pentru modul in care se implementeaza o astfel de functie este dat in fisierul "dltest.c".
Problema: Construiti un program (executabil), care dupa ce saluta utilizatorul citeste in mod repetat expresii, afisind rezultatul evaluarii expresiei. Programul se termina cind utilizatorul introduce stop.
Exemplu:
shell$ calc
Hello john
> 1+3
4
> stop
shell$
Observatii: