See also section 1.6.5 for more on naming conventions and standard methods.
The general philosophy for C++ classes is that a “half-created” object should not be possible - that is, the constructor should either succeed with a completely usable object or it should throw an exception. This API tries to follow that philosophy, but there are some important exceptions and caveats. (For more on how the C++ and Prolog exceptions interrelate, see section 1.15.)
Most of the PL_*() functions have corresponding wrapper methods. For example, PlTerm::get_atom() calls Plx_get_atom(), which calls PL_get_atom(). If the PL_get_atom() has an error, it creates a Prolog error; the Plx_get_atom() wrapper checks for this and converts the error to a C++ exception, which is thrown; upon return to Prolog, the exception is turned back into a Prolog error. Therfore, code typically does not need to check for errors.
Some functions return false to indicate either failure 
or an error, for example PlTerm::unify_term(); 
for such methods, a check is made for an error and an exception is 
thrown, so the return value of
false only means failure. (The whole thing can be wrapped 
in
PlCheckFail(), in which case a PlFail 
exception is thrown, which is converted to failure in Prolog.) For more 
on this, see
section 1.6.4, and for handling 
failure, see
section 1.13.1.
For PL_*() functions that take or return char* or
wchar_t* values, there are also wrapper functions and 
methods that use std::string or std::wstring. 
Because these copy the values, there is usually no need to enclose the 
calls with
PlStringBuffers (which wraps PL_STRING_MARK() and
PL_STRING_RELEASE()). See also the rationale for string:
section 1.8.2.
Many of the classes (PlAtom, PlTerm, etc.) 
are thin wrappers around the C interface's types (atom_t,
term_t, etc.). As such, they inherit the concept of “null” from 
these types (which is abstracted as PlAtom::null,
PlTerm::null, etc., which typically is equivalent to
0). Normally, you shouldn't need to check whether the 
object is “fully created” , for the rare situations where a 
check is needed, the methods is_null() 
and not_null() are provided.
Most of the classes have constructors that create a “complete” object. For example,
PlAtom foo("foo");
will ensure that the object foo is useable and will 
throw an exception if the atom can't be created. However, if you choose 
to create a PlAtom object from an atom_t 
value, no checking is done (similarly, no checking is done if you create 
a PlTerm object from a term_t value).
In many situations, you will be using a term; for these, there are special constructors. For example:
PlTerm_atom foo("foo"); // Same as PlTerm(PlAtom("foo"))
PlTerm_string str("a string");
To help avoid programming errors, some of the classes do not have a 
default “empty” constructor. For example, if you with to 
create a
PlAtom that is uninitialized, you must explicitly use
PlAtom(PlAtom::null). 
This make some code a bit more cumbersome because you can't omit the 
default constructors in struct initalizers.
Many of the classes have an as_string() 
method7This might be changed in 
future to to_string(), to be consistent with std::to_string(), 
which is useful for debugging.
The method names such as
as_int32_t() were chosen itnstead of to_int32_t() because 
they imply that the representation is already an int32_t, 
and not that the value is converted to a int32_t. That is, 
if the value is a float, int32_t will fail with an error 
rather than (for example) truncating the floating point value to fit 
into a 32-bit integer.
Many of the classes wrap long-lived items, such as atoms, functors, 
predicates, or modules. For these, it's often a good idea to define them 
as static variables that get created at load time, so that 
a lookup for each use isn't needed (atoms are unique, so
PlAtom("foo") requires 
a lookup for an atom foo and creates one if it isn't 
found).
C code sometimes creates objects “lazily” on first use:
void my_function(...)
{ static atom_t ATOM_foo = 0;
   ...
  if ( ! foo  )
     foo = PL_new_atom("foo");
   ...
}
For C++, this can be done in a simpler way, because C++ will call a 
local “static” constructor on first use.
void my_function(...)
{ static PlAtom ATOM_foo("foo");
}
The class PlTerm (which wraps term_t) is 
the most used. Although a PlTerm object can be created from 
a term_t value, it is intended to be used with a 
constructor that gives it an initial value. The default constructor 
calls PL_new_term_ref() and throws an exception if this fails. 
The various constructors are described in
section 1.6.6. Note that the 
default constructor is not public; to create a “variable” term, 
you should use the subclass constructor PlTerm_var().