- 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
- 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
The example below opens a query to the predicate is_a/2 to find the ancestor of‘me'. The reference to the predicate is valid for the duration of the process or until PL_cleanup() is called (see PL_predicate() for details) and may be cached by the client.
char * ancestor(const char *me) { term_t a0 = PL_new_term_refs(2); static predicate_t p; if ( !p ) p = PL_predicate("is_a", 2, "database"); PL_put_atom_chars(a0, me); PL_open_query(NULL, PL_Q_PASS_EXCEPTION, p, a0); ... }
TRUE
if a solution was found, or FALSE
to
indicate the query could not be proven. This function may be called
repeatedly until it fails to generate all solutions to the query.FALSE
and the exception is accessible
through PL_exception(0)
.\+ \+ Goal
. This reduces the need for
garbage collection, but also rewinds side effects such as setting global
variables using b_setval/2.0
if the
current thread is not executing any queries.TRUE
if the call succeeds, FALSE
otherwise.
Figure 7 shows
an example to obtain the number of defined atoms. All checks are omitted
to improve readability.
12.4.12 Discarding Data
The Prolog data created and term references needed to set up the call and/or analyse the result can in most cases be discarded right after the call. PL_close_query() allows for destroying the data, while leaving the term references. The calls below may be used to destroy term references and data. See figure 7 for an example.
- fid_t PL_open_foreign_frame()
- Create a foreign frame, holding a mark that allows the system to undo
bindings and destroy data created after it, as well as providing the
environment for creating term references. This function is called by the
kernel before calling a foreign predicate. Raise a resource exception
and returns
(fid_t)0
on failure. - void PL_close_foreign_frame(fid_t id)
- Discard all term references created after the frame was opened. All other Prolog data is retained. This function is called by the kernel whenever a foreign function returns control back to Prolog.
- void PL_discard_foreign_frame(fid_t id)
- Same as PL_close_foreign_frame(), but also undo all bindings made since the open and destroy all Prolog data.
- void PL_rewind_foreign_frame(fid_t id)
- Undo all bindings and discard all term references created since the frame was created, but do not pop the frame. That is, the same frame can be rewound multiple times, and must eventually be closed or discarded.
It is obligatory to call either of the two closing functions to discard a foreign frame. Foreign frames may be nested.
int count_atoms() { fid_t fid = PL_open_foreign_frame(); term_t goal = PL_new_term_ref(); term_t a1 = PL_new_term_ref(); term_t a2 = PL_new_term_ref(); functor_t s2 = PL_new_functor(PL_new_atom("statistics"), 2); int atoms; PL_put_atom_chars(a1, "atoms"); PL_cons_functor(goal, s2, a1, a2); PL_call(goal, NULL); /* call it in current module */ PL_get_integer(a2, &atoms); PL_discard_foreign_frame(fid); return atoms; }
12.4.13 String buffering
Many of the functions of the foreign language interface involve strings. Some of these strings point into static memory like those associated with atoms. These strings are valid as long as the atom is protected against atom garbage collection, which generally implies the atom must be locked using PL_register_atom() or be part of an accessi