Abstract: The availability of good foreign language interfaces is fundamental for the interoperability of different programming languages. While this observation is true for any language, it is especially important for non-mainstream languages such as Prolog, since they are likely to be discarded when shortcomings of the interfaces suggest the adoption of just one implementation language. In this paper we review some existing Prolog foreign language interfaces, trying to highlight both the important characteristics they share and the features that distinguish them from one another. We argue that even a basic, but standard Prolog foreign language interface could significantly contribute to increasing the adoption of Prolog for those subsystems where it is ``the right language''. Finally we suggest which steps could be taken in this direction.
Prolog_term from_to_list(int n, int m) { int i; Prolog_term tail = nil(); for (i = m; i >= n; --i) tail = make_cons(make_integer(i), tail); return tail; }Figure 1: Constructing a Prolog list from C: A functional view.
#define CHECK(f) if (f == 0) return 0 int from_to_list(int n, int m, Prolog_term res) { int i; Prolog_term head, tail; new_Prolog_term(head); new_Prolog_term(tail); CHECK(put_atom(tail, nil())); for (i = m; i >= n; --i) { CHECK(put_integer(head, i)); CHECK(put_cons(tail, head, tail)); } CHECK(put_term(res, tail)); return 1; }Figure 2: Constructing a Prolog list from C: A procedural view. In fact error returning should be more complicated and make untrailing, etc. This can however be left to the general fail mechanism of Prolog.
Besides the names given to the operations in the interface, there are different flavors in which they may come. A functional interface (we apologize for this abuse of terminology) returns the data as function results, and often helps to have compact C code (see Figure 1). A procedural interface usually needs intermediate variables and more lengthy code, but it offers a way to return error codes very similar to what a C programmer would expect (Figure 2). Both can however be reconciled by selecting a special, non-valid term to denote an error situation (Figure 3). While comparable, they are clearly incompatible.#define CHECK(f) if ((f) == Prolog_term_error) return Prolog_term_error; Prolog_term from_to_list(int n, int m) { int i; Prolog_term tail, head; CHECK(tail = nil()); for (i = m; i >= n; --i) { CHECK(head = make_integer(i)); CHECK(tail = make_cons(head, tail)); } return tail; }Figure 3: Constructing a Prolog list from C: Functions with designated errors.
Here is, for each of the features corresponding to rows in the table, the meaning of the symbols used in the table:
Syst./Charac. B-Prolog Bin Ciao Eclipse GNU SICStus SWI XSB YAP Glue code m m b m b b m b m Int. style f l f f f p p p f Term constr. t b b b b b b t b Non-det. n n s n y n y n y Exceptions n n y n y y y n n C to Prolog r r r y r r r y r (De)Init n n i n n b n n n Compilation m m a m m e m a m Linking s s d b s b b s d
Table 1: Summary of gathered information
'.'/2
),
others where a list is either a cons structure or nil
([]/0
), others that reserve the word list for properly
terminated Prolog lists.
:- initialization
, and a
:- deinitialization
whose associated goal is called when the
module is unloaded would be useful in several cases --- especially if a
normal (i.e., not an abortion) program shutdown also unloads the
modules. In that case, if the C code is seen at the same level as
Prolog, foreign code initialization and deinitialization is just a
particular case which can be handled by the Prolog mechanism.