• 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
          • Overview of accessing and changing values
          • The class PlRegister
          • The class PlQuery
          • The PREDICATE and PREDICATE_NONDET macros
          • Exceptions
          • Embedded applications
          • Considerations
          • Conclusions

1.5 The life of a PREDICATE

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.6You 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 - success
  • false - failure or an error (see section 1.15 and Prolog exceptions in foreign code).
  • “retry” - for non-deterministic predicates, gives a “context” for backtracking / redoing the call for the next solution.
If a predicate fails, it could be simple failure (the equivalent of calling the builtin fail/0 predicate) or an error (the equivalent of calling the throw/1 predicate). When a Prolog 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 for failure, which can become cumbersome; with the C++ API, most errors are thrown as exceptions to the enclosing PREDICATE() wrapper, and turned back into Prolog errors.

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;
}

ClioPatria (version V3.1.1-51-ga0b30a5)