- 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.9 The class PlFail (version 2)
The PlFail
class is used for short-circuiting a function
when failure or an exception occurs and any errors will be handled in
the code generated by the PREDICATE()
macro. See also
section 2.16.2).
For example, this code, using the C API:
PREDICATE(unify_zero, 1) { if ( !PL_unify_integer(A1.unwrap(), 0) ) return false; // could be an error or failure Sprintf("It's zero!\n"); return true; }
can instead be written this way, using the C++ API:
PREDICATE(unify_zero, 1) { PlCheckFail(A1.unify_integer(0)); Sprintf("It's zero!\n"); return true; }
Using throw PlFail()
in performance-critical code
can cause a signficant slowdown. A simple benchmark showed a 15x to 20x
slowdown using throw PlFail()
compared to return
false
(comparing the first code sample above with the second and
third samples; the speed difference seems to have been because in the
second sample, the compiler did a better job of inlining). However, for
most code, this difference will be barely noticeable. And if the code
usually succeeds, there is no significant difference.
There was no significant performance difference between the C++ version and this C version:
static foreign_t unify_zero(term_t a1) { return PL_unify_integer(a1, 0); }
2.9.1 PlCheckFail(), PlCheckEx(), and PlCheck_PL() convenience functions
If one of the C PL_*() functions in SWI-Prolog.h
returns
failure, this can be either a Prolog-style failure (e.g. from
PL_unify() or PL_next_solution()) or an error. If the
failure is due to an error, it's usually best to immediately return to
Prolog - and this can be done with the PlCheckEx() function,
which turns a Prolog error into a C++ PlException
. PlCheckFail()
calls PlCheckEx() and additionally throws PlFail() if the
failure is for Prolog failure.
PlCheckEx() calls PL_exception() to see if there is a
Prolog exception; if so, the Prolog exception is converted to a
PlException
object, which is then thrown. For more details
on the C++ exceptions, see section 2.14.
- void PlCheckFail(bool rc)
- If rc is
false
, throwPlFail
to return control to Prolog with failure. - C_t PlWrap(C_t rc, qid_t qid = 0)
- If rc indicates failure or an error, check for an error and
throw a
PlException
if there was one; otherwise, return the rc. - void PlEx(C_t rc, qid_t qid = 0)
- If rc is “false” (non-zero), throw
PlFail
to return control to Prolog with failure. This is the same as PlCheckFail() except it can also specify aqid_t
query ID.