- Documentation
- Reference manual
- Packages
- A C++ interface to SWI-Prolog
- A C++ interface to SWI-Prolog (Version 2)
- Summary of changes between Versions 1 and 2
- Sample code (version 2)
- Introduction (version 2)
- The life of a PREDICATE (version 2)
- Overview (version 2)
- Examples (version 2)
- Rationale for changes from version 1 (version 2)
- Porting from version 1 to version 2
- The class PlFail (version 2)
- Overview of accessing and changing values (version 2)
- The class PlRegister (version 2)
- The class PlQuery (version 2)
- The PREDICATE and PREDICATE_NONDET macros (version 2)
- Exceptions (version 2)
- Embedded applications (version 2)
- Considerations (version 2)
- Conclusions (version 2)
- A C++ interface to SWI-Prolog (Version 2)
- A C++ interface to SWI-Prolog
2.4 The life of a PREDICATE (version 2)
A foreign predicate is defined using the PREDICATE()
macro, plus a few variations on this, such as
PREDICATE_NONDET(), NAMED_PREDICATE(),
and
NAMED_PREDICATE_NONDET().
These define an internal name for the function, register it with the
SWI-Prolog runtime (where it will be picked up by the use_foreign_library/1
directive), and define the names A1
, A2
, etc.
for the arguments.7You can define
your own names for the arguments, for example: auto dir=A1, db=A2;
or PlTerm options(A3);
. If a non-deterministic
predicate is being defined, an additional parameter handle
is defined (of type
PlControl
).
The foreign predicate returns a value:
true
- successfalse
- failure or an error (see section 2.14 and Prolog exceptions in foreign code).- “retry” - for non-deterministic predicates, gives a “context” for backtracking / redoing the call for the next solution.
The C++ API provides Plx_*() functions that are the same as the PL_*() functions except that where appropriate they check for exceptions and thrown a PlException().
Addditionally, the function PlCheckFail()
can be used to check for failure and throw a PlFail
exception that is handled before returning to Prolog with failure.
The following three snippets do essentially the same thing (for
implementing the equivalent of =/2); however the first version (with
PlTerm::unify_term())
and second version (with Plx_unify()) throw a C++ PlExceptionFail
exception if there's an error and otherwise return true
or false
;
the third version (with PlCheckFail())
throws a PlFail
exception for failure (and PlExceptionFail
for an error) and otherwise returns true
- the PREDICATE()
wrapper handles all of these appropriately and reports the same result
back to Prolog; but you might wish to distinguish the two situations in
more complex code.
PREDICATE(eq, 2) { return A1.unify_term(A2); }
PREDICATE(eq, 2) { return Plx_unify(A1.unwrap(), A2.unwrap())); }
PREDICATE(eq, 2) { PlCheckFail(A1.unify_term(A2)); return true; }