2.4 Overview (version 2)
AllApplicationManualNameSummaryHelp

  • Documentation
    • Reference manual
    • Packages
      • A C++ interface to SWI-Prolog
        • A C++ interface to SWI-Prolog (Version 2)
          • Overview (version 2)
            • Design philosophy of the classes
            • Summary of classes
            • Naming conventions, utility functions and methods (version 2)

2.4.3 Naming conventions, utility functions and methods (version 2)

See also section 2.4.1.

The classes all have names starting with "Pl", using CamelCase; this contrasts with the C functions that start with "PL_" and use underscores.

The wrapper classes (PlFunctor, PlAtom, PlTerm) all contain a field C_ that contains the wrapped value (functor_t, atom_t, term_t respectively).

The wrapper classes (which subclass WrappedC< ...) all define the following methods and constants:

  • default constructor (sets the wrapped value to null)
  • constructor that takes the wrapped value (e.g., for PlAtom, the constructor takes an atom_t value).
  • C_ - the wrapped value. This can be used directly when calling C functions, for example, if t and a are of type PlTerm and PlAtom: Plcheck(PL_put_atom(t.C_,a.C_)).
  • null - the null value (typically 0, but code should not rely on this)
  • is_null(), not_null() - test for the wrapped value being null.
  • reset() - set the wrapped value to null
  • reset(new_value) - set the wrapped value
  • verify() - if the wrapped value (C_) is null, throw a PlFail() exception. Typically, this check is done after an allocation function such as Plnew_term_ref() returns a null value, so the PlFail() is turned into a a resource error. However, if there is no pending exception, this results in simple failure (see section 2.18.2).
  • The bool operator is turned off - you should use not_null() instead.10The reason: a bool conversion causes ambiguity with PlAtom(PlTterm) and PlAtom(atom_t).

The C_ field can be used wherever a atom_t or term_t is used. For example, the PL_scan_options() example code can be written as follows. Note the use of &callback.C_ to pass a pointer to the wrapped term_t value.

PREDICATE(mypred, 2)
{ auto options = A2;
  int        quoted = false;
  size_t     length = 10;
  PlTerm_var callback;

  PlCheck(PL_scan_options(options, 0, "mypred_options", mypred_options,
                          &quoted, &length, &callback.C_));
  callback.record(); // Needed if callback is put in a blob that Prolog doesn't know about.
                     // If it were an atom (OPT_ATOM): register_ref().

  <implement mypred>
}

For functions in SWI-Prolog.h that don't have a C++ equivalent in SWI-cpp2.h, PlCheck() is a convenience function that checks the return code and throws a PlFail exception on failure. The PREDICATE() code catches PlFail exceptions and converts them to the foreign_t return code for failure. If the failure from the C function was due to an exception (e.g., unification failed because of an out-of-memory condition), the foreign function caller will detect that situation and convert the failure to an exception.

The "getter" methods for PlTerm all throw an exception if the term isn't of the expected Prolog type. Where possible, the "getters" have the same name as the underlying type; but this isn't possible for types such as int or float, so for these the name is prepended with "as_".

"Getters" for integers have an additionnal problem, in that C++ doesn't define the sizes of int and long, nor for size_t. It seems to be impossible to make an overloaded method that works for all the various combinations of integer types on all compilers, so there are specific methods for int64_t, uint64_t, size_t.

In some cases,it is possible to overload methods; for example, this allows the following code without knowing the exact definition of size_t:

PREDICATE(p, 1)
{ size_t sz;
  A1.integer(&sz);
     ...
}

It is strongly recommended that you enable conversion checking. For example, with GNU C++, these options (possibly with -Werror: -Wconversion -Warith-conversion -Wsign-conversion -Wfloat-conversion.

There is an additional problem with characters - C promotes them to int but C++ doesn't. In general, this shouldn't cause any problems, but care must be used with the various getters for integers.