- 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
- Introduction (version 2)
- The life of a PREDICATE (version 2)
- Overview (version 2)
- Examples (version 2)
- Rational for changes from version 1 (version 2)
- Porting from version 1 to version 2
- The class PlFail (version 2)
- The class PlTerm (version 2)
- The class PlTermv (version 2)
- The class PlAtom - Supporting Prolog constants (version 2)
- Unification and foreign frames (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.3 The life of a PREDICATE (version 2)
A foreign predicate is defined using the PREDICATE() macro.6Plus
a few variations on this, such as PREDICATE_NONDET(), NAMED_PREDICATE(),
and NAMED_PREDICATE_NONDET().
This defines an internal name for the function, registers it with the
SWI-Prolog runtime (where it will be picked up by the use_foreign_library/1
directive), and defines the names A1
, A2
, etc.
for the arguments.7You can define
your own names for the arguments, for example: auto x=A1, y=A2,
result=A3;
. If a non-deterministic predicate is
being defined, an additional parameter handle
is defined
(of type
control_t
).
The foreign predicate returns a value of true
or false
to indicate whether it succeeded or failed.8Non-deterministic
predicates can also return a "retry" value. If a predicate
fails, it could be simple failure (the equivalent of calling the builtin fail/0)
or an error (the equivalent of calling throw/1).
When an exception is raised, it is important that a return be made to
the calling environment as soon as possible. In C code, this requires
checking every call to check for failure, which can become cumbersome.
C++ has exceptions, so instead the code can wrap calls to PL_*()
functions with
PlCheck(), which will do throw PlFail()
to exit from
the top level of the foreign predicate, and handle the failure or
exception appropriately.
The following three snippets do the same thing (for implementing the equivalent of =/2):
PREDICATE(eq, 2) { PlCheck(A1.unify_term(A2)); return true; }
PREDICATE(eq, 2) { return A1.unify_term(A2); }
PREDICATE(eq, 2) { PlCheck(PL_unify(A1.C_, A2.C_)); return true; }