• Places
    • Home
    • Graphs
    • Prefixes
  • Admin
    • Users
    • Settings
    • Plugins
    • Statistics
  • CPACK
    • Home
    • List packs
    • Submit pack
  • Repository
    • Load local file
    • Load from HTTP
    • Load from library
    • Remove triples
    • Clear repository
  • Query
    • YASGUI SPARQL Editor
    • Simple Form
    • SWISH Prolog shell
  • Help
    • Documentation
    • Tutorial
    • Roadmap
    • HTTP Services
  • Login

1 A C++ interface to SWI-Prolog
All Application Manual Name SummaryHelp

  • Documentation
    • Reference manual
    • Packages
      • A C++ interface to SWI-Prolog
        • A C++ interface to SWI-Prolog
          • Summary of changes between Versions 1 and 2
          • A simple example
          • Sample code
          • Introduction
          • The life of a PREDICATE
          • Overview
          • Examples
          • Rationale for changes from version 1
          • Porting from version 1 to version 2
          • The class PlFail
            • PlCheckFail(), and PlEx() convenience functions
          • Overview of accessing and changing values
          • The class PlRegister
          • The class PlQuery
          • The PREDICATE and PREDICATE_NONDET macros
          • Exceptions
          • Embedded applications
          • Considerations
          • Conclusions

1.10 The class PlFail

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 1.17.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);
}

1.10.1 PlCheckFail(), and PlEx() 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 PlEx() function, which turns a Prolog error into a C++ PlException. PlCheckFail() calls PlEx() and additionally throws PlFail() if the failure is for Prolog failure.

PlEx() 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 1.15.

void PlCheckFail(bool rc)
If rc is false, throw PlFail 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 a qid_t query ID.

ClioPatria (version V3.1.1-51-ga0b30a5)