A foreign predicate is defined using the PREDICATE() macro,
pPlus a few variations on this, such as
PREDICATE_NONDET(), NAMED_PREDICATE(),
and
NAMED_PREDICATE_NONDET().
This defines an internal name for the function, registers it with the
SWI-Prolog runtime (where it will be picked up by the use_foreign_library/1
directive), and defines the names A1, A2, etc.
for the arguments.8You can define
your own names for the arguments, for example: auto x=A1, y=A2,
result=A3;. If a non-deterministic predicate is
being defined, an additional parameter handle is defined
(of type
PlControl).
The foreign predicate returns a value of true or false
to indicate whether it succeeded or failed.9Non-deterministic
predicates can also return a "retry" value. 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. C++ has exceptions, so instead the code can wrap calls to
PL_*() functions with PlCheck_PL() or
PlCheckEx(), which will throw a PlException() to exit from the
top level of the foreign predicate, and handle the failure or exception
appropriately.
The following three snippets do the same thing (for implementing the equivalent of =/2):
PREDICATE(eq, 2)
{ PlCheckFail(A1.unify_term(A2));
return true;
}
PREDICATE(eq, 2)
{ return A1.unify_term(A2);
}
PREDICATE(eq, 2)
{ return PlWrap<int>(PL_unify(A1.C_, A2.C_));
}