Interfaces to other languages are available for virtually all commercial Prolog systems. They differ on the implementation, but the idea is shared among them: linking an object file to the executable of the Prolog engine, and then using an internal convention to call from Prolog and to pass and retrieve data. Calling Prolog from other languages is also possible: the Prolog engine is stored as a library which is linked against the program which will use it. As an example, we will make a low level, complete developing of an example of accessing to a UNIX standard library.
The library we will use is the so-called curses library, which allows cursor control in a variety of terminals, independently of the actual terminal used. There is a lot of functionality in that library, including making text-based subwindows, etc. But, in order to keep the example short, we will make interfaces only to two functions: initsrc(), which initializes the library, and move(), which positions the cursor at the coordinates given. We will access those C functions using the Prolog predicates init_term/0 and tmove/2.
The first step is writing some C glue code:
#include <curses.h> static WINDOW * prolog_window; void init_term() { prolog_window = initscr(); } void tmove(h, v) long h, v; { move((int)h, (int)v);
These C functions will be accessed from Prolog. init_term() just calls initsrc() and saves the returned WINDOW * structure in a variable. This variable is not used anywhere else, but it could be needed if other library functions are accessed. This code is compiled to an object file (for example, term_control.o), and that is all what is needed to do in the C side of the project.
On the Prolog side we have to declare some things: which object file we want to link, which additional libraries are needed by that object file, if any (as in our case), which functions need to be called when the corresponding predicates are accessed, and how the data is to be converted (because Prolog data is usually stored differently from data in other languages). Fortunately, almost all the low-level details are taken care of by Prolog. The necessary declarations are:
foreign_file('term_control.o', [init_term,tmove]). foreign(init_term, init_term). foreign(tmove, tmove(+integer, +integer)).
The first fact says that the object file term_control.o has the C functions init_term and tmove. foreign/2 keeps information about which C function should be called for every Prolog predicate, and which arguments the C functions expect to receive. All that is needed now is to call a builtin predicate which makes the linkage at runtime, and installs Prolog entries for these C predicates. This is done by calling
?- load_foreign_files(['term_control.o'], ['-lcurses', '-ltermcap']).
either at the prompt or somewhere in the program. Note that it also provides names of libraries which are needed by the C code we have just written.