Specifying the Argument Passing Interface

The argument passing interface is specified by defining facts for foreign/3 of the form:

     foreign(+Routine, +Language, +PredicateSpecification)

Routine is an atom that names a foreign code routine and Language is an atom (either c, pascal, or fortran) that names the language in which the routine is written.

Please note: Assembly code can be loaded if it emulates the exact calling conventions of one of C, FORTRAN, or Pascal. Language is then chosen, accordingly, to be one of c, fortran, or pascal.

PredicateSpecification specifies the Prolog name given to the foreign code routine and how its arguments will be passed to and from the foreign code routine.

PredicateSpecification is of the form:

     PredicateName(ArgSpec1, ArgSpec2, ...ArgSpecN)

where PredicateName is the name of the Prolog predicate (an atom) and each ArgSpec is an argument specification for each argument of the predicate. An ArgSpec informs the Prolog system how to pass or receive a Prolog term in the corresponding argument position.

Prolog checks the types of the input arguments; a foreign function call will raise an exception if any input argument is not of the right type.

If the argument passed is an atomic object then the interface automatically converts between Prolog's representation of the data and the representation expected by the foreign function. Thus the external function does not need to know how Prolog represents atoms, integers, or floats in order to communicate with Prolog. This feature simplifies the integration of foreign code with Prolog; in particular, it makes it easier to interface directly with already-written functions in libraries and other programs. It also allows for compatibility with later versions of Quintus Prolog and with versions of Quintus Prolog running on other hardware.

Please note: The only atomic object that cannot be passed directly through the foreign interface is a db_reference. db_references can be passed to foreign code using the general term passing mechanism using +term and -term. You can take apart and build db_references in foreign language using the QP_get_db_reference() and QP_put_db_reference() functions.

On the other hand, generic Prolog terms passed to a foreign function (using +term) are not converted to any representation in the foreign language. Instead the foreign function gets a reference to a Prolog term. A set of functions/macros is provided to type test, access and create Prolog terms through these references (see cfu). Similarly when a generic term is returned (using -term or [-term]) from a foreign function there is no conversion of any data structures in the foreign language into an equivalent Prolog representation. The foreign function has to return a reference to a Prolog term, which it originally got from Prolog or from one of the functions/macros provided to manipulate Prolog terms (the QP_put* and QP_cons* families of functions) Further details in fli-p2f-trm.

Arguments are passed to foreign functions in the same order as they appear in the Prolog call, except for the return value. At most one "return value" argument can be specified; that is, there can be only one [-integer], [-float], [-atom], [-string], [-string(N)], or [-address(typename)] specification. There need not be any "return value" argument, in which case the value returned by the function is ignored. Both input and output specifications cause data to be passed to the foreign function (except of course for the "return value" argument, if present). Each input argument is appropriately converted and passed, by reference or by value, depending on the language's calling convention, and each output argument is passed as a pointer through which the foreign function will send back the result. Note that for C, input arguments are always passed by value.

Prolog assumes that a foreign function will return output arguments of the specified types; if it does not, the result is unpredictable. Normally, unbound variables will be supplied in the Prolog goal for all the output argument positions. However, any value may be supplied for an output argument; when the foreign function has been completed, its outputs are unified with the values supplied and a failure to unify results in the failure of the Prolog goal.

Detailed information about passing particular data types through the foreign interface can be found in fli-p2f-int through fli-p2f-poi. Examples showing the correct use of the foreign interface are presented in fli-p2f-fex.