12.4 The Foreign Include File
AllApplicationManualNameSummaryHelp

  • Documentation
    • Reference manual
      • Foreign Language Interface
        • The Foreign Include File
          • Argument Passing and Control
          • Atoms and functors
          • Analysing Terms via the Foreign Interface
          • Constructing Terms
          • Unifying data
          • Convenient functions to generate Prolog exceptions
          • Foreign language wrapper support functions
          • Serializing and deserializing Prolog terms
          • BLOBS: Using atoms to store arbitrary binary data
          • Exchanging GMP numbers
          • Calling Prolog from C
          • Discarding Data
          • String buffering
          • Foreign Code and Modules
          • Prolog exceptions in foreign code
          • Catching Signals (Software Interrupts)
          • Miscellaneous
            • Term Comparison
            • Recorded database
            • Database
            • Getting file names
            • Dealing with Prolog flags from C
          • Errors and warnings
          • Environment Control from Foreign Code
          • Querying Prolog
          • Registering Foreign Predicates
          • Foreign Code Hooks
          • Storing foreign data
          • Embedding SWI-Prolog in other applications
    • Packages

12.4.17 Miscellaneous

12.4.17.1 Term Comparison

int PL_compare(term_t t1, term_t t2)
Compares two terms using the standard order of terms and returns -1, 0 or 1. See also compare/3.
int PL_same_compound(term_t t1, term_t t2)
Yields TRUE if t1 and t2 refer to physically the same compound term and FALSE otherwise.

12.4.17.2 Recorded database

In some applications it is useful to store and retrieve Prolog terms from C code. For example, the XPCE graphical environment does this for storing arbitrary Prolog data as slot-data of XPCE objects.

Please note that the returned handles have no meaning at the Prolog level and the recorded terms are not visible from Prolog. The functions PL_recorded() and PL_erase() are the only functions that can operate on the stored term.

Two groups of functions are provided. The first group (PL_record() and friends) store Prolog terms on the Prolog heap for retrieval during the same session. These functions are also used by recorda/3 and friends. The recorded database may be used to communicate Prolog terms between threads.

record_t PL_record(term_t +t)
Record the term t into the Prolog database as recorda/3 and return an opaque handle to the term. The returned handle remains valid until PL_erase() is called on it. PL_recorded() is used to copy recorded terms back to the Prolog stack. Currently aborts the process with a fatal error on failure. Future versions may raise a resource exception and return (record_t)0.
record_t PL_duplicate_record(record_t record)
Return a duplicate of record. As records are read-only objects this function merely increments the records reference count. Returns (record_t)0 if the record is an external record (see PL_record_external()).
int PL_recorded(record_t record, term_t -t)
Copy a recorded term back to the Prolog stack. The same record may be used to copy multiple instances at any time to the Prolog stack. Returns TRUE on success, and FALSE if there is not enough space on the stack to accommodate the term. See also PL_record() and PL_erase().
void PL_erase(record_t record)
Remove the recorded term from the Prolog database, reclaiming all associated memory resources.

The second group (headed by PL_record_external()) provides the same functionality, but the returned data has properties that enable storing the data on an external device. It has been designed for fast and compact storage of Prolog terms in an external database. Here are the main features:

  • Independent of session
    Records can be communicated to another Prolog session and made visible using PL_recorded_external().
  • Binary
    The representation is binary for maximum performance. The returned data may contain zero bytes.
  • Byte-order independent
    The representation can be transferred between machines with different byte order.
  • No alignment restrictions
    There are no memory alignment restrictions and copies of the record can thus be moved freely. For example, it is possible to use this representation to exchange terms using shared memory between different Prolog processes.
  • Compact
    It is assumed that a smaller memory footprint will eventually outperform slightly faster representations.
  • Stable
    The format is designed for future enhancements without breaking compatibility with older records.
char * PL_record_external(term_t +t, size_t *len)
Record the term t into the Prolog database as recorda/3 and return an opaque handle to the term. The returned handle remains valid until PL_erase_external() is called on it. Currently aborts the process with a fatal error on failure. Future versions may raise a resource exception and return (record_t)0.

It is allowed to copy the data and use PL_recorded_external() on the copy. The user is responsible for the memory management of the copy. After copying, the original may be discarded using PL_erase_external().

PL_recorded_external() is used to copy such recorded terms back to the Prolog stack.

int PL_recorded_external(const char *record, term_t -t)
Copy a recorded term back to the Prolog stack. The same record may be used to copy multiple instances at any time to the Prolog stack. See also PL_record_external() and PL_erase_external().
int PL_erase_external(char *record)
Remove the recorded term from the Prolog database, reclaiming all associated memory resources.

12.4.17.3 Database

int PL_assert(term_t t, module_t m, int flags)
Provides direct access to asserta/1 and assertz/1 by asserting t into the database in the module m. Defined flags are:
PL_ASSERTZ
Add the new clause as last. Calls assertz/1. This macros is defined as 0 and thus the default.
PL_ASSERTA
Add the new clause as first. Calls asserta/1.
PL_CREATE_THREAD_LOCAL
If the predicate is not defined, create it as thread-local. See thread_local/1.
PL_CREATE_INCREMENTAL
If the predicate is not defined, create it as incremental see table/1 and section 7.7.

On success this function returns TRUE. On failure FALSE is returned and an exception is left in the environment that describes the reason of failure. See PL_exception().

This predicate bypasses creating a Prolog callback environment and is faster than setting up a call to assertz/1. It may be used together with PL_chars_to_term(), but the typical use case will create a number of clauses for the same predicate. The fastest way to achieve this is by creating a term that represents the invariable structure of the desired clauses using variables for the variable sub terms. Now we can loop over the data, binding the variables, asserting the term and undoing the bindings. Below is an example loading words from a file that contains a word per line.

#include <SWI-Prolog.h>
#include <stdio.h>
#include <string.h>

#define MAXWLEN 256

static foreign_t
load_words(term_t name)
{ char *fn;

  if ( PL_get_file_name(name, &fn, PL_FILE_READ) )
  { FILE *fd = fopen(fn, "r");
    char word[MAXWLEN];
    module_t m = PL_new_module(PL_new_atom("words"));
    term_t cl = PL_new_term_ref();
    term_t w  = PL_new_term_ref();
    fid_t fid;

    if ( !PL_unify_term(cl, PL_FUNCTOR_CHARS, "word", 1, PL_TERM, w) )
      return FALSE;

    if ( (fid = PL_open_foreign_frame()) )
    { while(fgets(word, sizeof word, fd))
      { size_t len;

        if ( (len=strlen(word)) )
        { word[len-1] = '\0';
          if ( !PL_unify_chars(w, PL_ATOM|REP_MB, (size_t)-1, word) ||
               !PL_assert(cl, m, 0) )
            return FALSE;
          PL_rewind_foreign_frame(fid);
        }
      }

      PL_close_foreign_frame(fid);
    }

    fclose(fd);
    return TRUE;
  }

  return FALSE;
}

install_t
install(void)
{ PL_register_foreign("load_words", 1, load_words, 0);
}

12.4.17.4 Getting file names

The function PL_get_file_name() provides access to Prolog filenames and its file-search mechanism described with absolute_file_name/3. Its existence is motivated to realise a uniform interface to deal with file properties, search, naming conventions, etc., from foreign code.

int PL_get_file_name(term_t spec, char **name, int flags)
Translate a Prolog term into a file name. The name is stored in the buffer stack described with the PL_get_chars() option BUF_STACK. Conversion from the internal UNICODE encoding is done using standard C library functions. flags is a bit-mask controlling the conversion process. Options are:
PL_FILE_ABSOLUTE
Return an absolute path to the requested file.
PL_FILE_OSPATH
Return the name using the hosting OS conventions. On MS-Windows, \ is used to separate directories rather than the canonical /.
PL_FILE_SEARCH
Invoke absolute_file_name/3. This implies rules from file_search_path/2 are used.
PL_FILE_EXIST
Demand the path to refer to an existing entity.
PL_FILE_READ
Demand read-access on the result.
PL_FILE_WRITE
Demand write-access on the result.
PL_FILE_EXECUTE
Demand execute-access on the result.
PL_FILE_NOERRORS
Do not raise any exceptions.
int PL_get_file_nameW(term_t spec, wchar_t **name, int flags)
Same as PL_get_file_name(), but returns the filename as a wide-character string. This is intended for Windows to access the Unicode version of the Win32 API. Note that the flag PL_FILE_OSPATH must be provided to fetch a filename in OS native (e.g., C:\x\y) notation.

12.4.17.5 Dealing with Prolog flags from C

Foreign code can set or create Prolog flags using PL_set_prolog_flag(). See set_prolog_flag/2 and create_prolog_flag/3. To retrieve the value of a flag you can use PL_current_prolog_flag().

int PL_set_prolog_flag(const char *name, int type, ...)
Set/create a Prolog flag from C. name is the name of the affected flag. type is one of the values below, which also dictates the type of the final argument. The function returns TRUE on success and FALSE on failure. This function can be called before PL_initialise(), making the flag available to the Prolog startup code.
PL_BOOL
Create a boolean (true or false) flag. The argument must be an int.
PL_ATOM
Create a flag with an atom as value. The argument must be of type const char *.
PL_INTEGER
Create a flag with an integer as value. The argument must be of type intptr_t *.
int PL_current_prolog_flag(atom_t name, int type, void *value)
Retrieve the value of a Prolog flag from C. name is the name of the flag as an atom_t (see current_prolog_flag/2). type specifies the kind of value to be retrieved, it is one of the values below. value is a pointer to a location where to store the value. The user is responsible for making sure this memory location is of the appropriate size/type (see the returned types below to determine the size/type). The function returns TRUE on success and FALSE on failure.
PL_ATOM
Retrieve a flag whose value is an atom. The returned value is an atom handle of type atom_t.
PL_INTEGER
Retrieve a flag whose value is an integer. The returned value is an integer of type int64_t.
PL_FLOAT
Retrieve a flag whose value is a float. The returned value is a floating point number of type double.
PL_TERM
Retrieve a flag whose value is a term. The returned value is a term handle of type term_t.