- 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
- 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
- The Foreign Include File
- Foreign Language Interface
- Packages
- Reference manual
- int PL_sigaction(int sig, pl_sigaction_t *act, pl_sigaction_t *oldact)
- Install or query the status for signal sig. The signal is an
integer between 1 and 64, where the where the signals up to 32 are
mapped to OS signals and signals above that are handled by Prolog's
synchronous signal handling. The
pl_sigaction_t
is a struct with the following definition:typedef struct pl_sigaction { void (*sa_cfunction)(int); /* traditional C function */ predicate_t sa_predicate; /* call a predicate */ int sa_flags; /* additional flags */ } pl_sigaction_t;
The
sa_flags
is a bitwise or ofPLSIG_THROW
,PLSIG_SYNC
andPLSIG_NOFRAME
. Signal handling is enabled ifPLSIG_THROW
is provided,sa_cfunction
orsa_predicate
is provided.sa_predicate
is a predicate handle for a predicate with arity 1. If no action is provided the signal handling for this signal is restored to the default before PL_initialise() was called.Finally, 0 (zero) may be passed for sig. In that case the system allocates a free signal in the Prolog range (32 ... 64). Such signal handler are activated using PL_thread_raise().
- void (*)() PL_signal(sig, func)
- This function is equivalent to the BSD-Unix signal() function,
regardless of the platform used. The signal handler is blocked while the
signal routine is active, and automatically reactivated after the
handler returns.
After a signal handler is registered using this function, the native signal interface redirects the signal to a generic signal handler inside SWI-Prolog. This generic handler validates the environment, creates a suitable environment for calling the interface functions described in this chapter and finally calls the registered user-handler.
By default, signals are handled asynchronously (i.e., at the time they arrive). It is inherently dangerous to call extensive code fragments, and especially exception related code from asynchronous handlers. The interface allows for synchronous handling of signals. In this case the native OS handler just schedules the signal using PL_raise(), which is checked by PL_handle_signals() at the call- and redo-port. This behaviour is realised by or-ing sig with the constant
PL_SIGSYNC
.230A better default would be to use synchronous handling, but this interface preserves backward compatibility.Signal handling routines may raise exceptions using PL_raise_exception(). The use of PL_throw() is not safe. If a synchronous handler raises an exception, the exception is delayed to the next call to PL_handle_signals();
- int PL_raise(int sig)
- Register sig for synchronous handling by Prolog. Synchronous signals are handled at the call-port or if foreign code calls PL_handle_signals(). See also thread_signal/2.
- int PL_handle_signals(void)
- Handle any signals pending from PL_raise(). PL_handle_signals()
is called at each pass through the call- and redo-port at a safe point.
Exceptions raised by the handler using PL_raise_exception()
are properly passed to the environment.
The user may call this function inside long-running foreign functions to handle scheduled interrupts. This routine returns the number of signals handled. If a handler raises an exception, the return value is -1 and the calling routine should return with
FALSE
as soon as possible. - int PL_get_signum_ex(term_t t, int *sig)
- Extract a signal specification from a Prolog term and store as an
integer signal number in sig. The specification is an
integer, a lowercase signal name without
SIG
or the full signal name. These refer to the same:9
,kill
andSIGKILL
. Leaves a typed, domain or instantiation error if the conversion fails.
12.4.18 Miscellaneous
12.4.18.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 andFALSE
otherwise.
12.4.18.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, andFALSE
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
(char*)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_record_external() will fail if the term contains blobs that cannot be serialized, such as streams.
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.18.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 failureFALSE
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.18.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.