Linking Foreign Functions to Prolog Procedures

When load_foreign_executable/1 or load_foreign_files/2 is called, it calls the hook predicates foreign_file/2 and foreign/3 in the current source module. These should have been previously defined by clauses of the form:

     foreign_file(FileName, [Function1,Function2,...,FunctionN]).
     
     foreign(Function1, Language, PredicateSpecification1).
     foreign(Function2, Language, PredicateSpecification2).
     ...
     foreign(FunctionN, Language, PredicateSpecificationN).
     

Example:

     foreign_file(math, [sin,cos,tan]).
     
     foreign(sin, c, sin(+float,[-float])).
     foreign(cos, c, cos(+float,[-float])).
     foreign(tan, c, tan(+float,[-float])).
     

Please note: If a Prolog module includes foreign code, all relevant foreign/[2,3] and foreign_file/2 facts should be loaded into that module and the load_foreign_executable/1 or load_foreign_files/2 command should be called from that module.

A foreign_file/2 fact lists the functions that will be provided by the associated (shared) object file. When using load_foreign_files/2, a fact of this form must be provided for each file specified in the ListOfFiles argument. The functions specified should be only those that are to be attached to Prolog procedures. Supporting functions that will not be called directly from Prolog should not be listed.

Each foreign/3 fact describes how a foreign function is to be attached to a Prolog procedure. PredicateSpecification specifies the Prolog procedure and also the argument passing interface (described below). A fact of this form must be provided for each function that is to be attached to a Prolog procedure.

When load_foreign_executable/1 or load_foreign_files/2 is called, the specified files are loaded into the running Prolog and then all the specified Prolog procedures are abolished and redefined to be links to the foreign functions. Calling one of the Prolog procedures now results in a call to a foreign function.

Prolog procedures can be directly linked to library functions. Note, however, that some functions shown in the library documentation are actually C macros (found in included .h files). In this case, the simplest approach is to write a C function that uses the macro and then link to that function.

You may abolish or redefine (using compile/1) any procedure that has been attached to a foreign function. This severs the link between the Prolog predicate and the foreign function. It is not possible to reestablish this link.

The foreign_file/2 and foreign/3 facts must be consistent whenever load_foreign_executable/1 or load_foreign_files/2 is called. They are, however, not used after this point and may be abolished, if desired.1.

The load_foreign_executable/1 and load_foreign_files/2 commands can be used any number of times in a Prolog session to load different foreign programs. For example:

     | ?- compile(f1),
          load_foreign_executable(f1),
          abolish([foreign/3, foreign_file/2]).
     | ?- compile(f2),
          load_foreign_executable(f2),
          abolish([foreign/3, foreign_file/2]).
     

Each compile/1 installs a new set of facts describing a set of functions to be loaded by load_foreign_executable/1. Unless you abolish all foreign/3 and foreign_file/2 facts before each compilation, Prolog will warn you that foreign/3 and foreign_file/2 have been previously defined in another file.

A better way to do this is to insert the call to load_foreign_executable into the file that defines foreign_file/2 and foreign/3 as an embedded command. For example, you could add the following command to the end of the file f1.pl:

     :-  load_foreign_executable(f1),
         abolish([foreign/3, foreign_file/2]).
     

so that compiling f1.pl will automatically load f1.so. This embedded command will also work when building a stand-alone program, as described in sap-srs.


Footnotes

  1. See example in the reference page for foreign/[2,3].