Foreign Language Interface (integers, exceptions)

Here are some notes from @jan (responding to private emails and bug reports), lightly edited. Please add to this thread (or start a new one) for more on the foreign language interface.

PL_cvt_* functions aren’t documented, and not in the online index yet. They are formally part of the wrapper generator for Quintus and SICStus. They are stable, so you can use them.
The duplication between this set and the PL_get_*_ex() and PL_unify_*() should be resolved some day (probably by making one set macros to the other or (better but less portable) making one set weak symbol aliases for the other).

PL_get_unsigned_ex() is PL_cvt_i_uint().

For PL_unify_unsigned() either cast to an int of a larger size or use pl_unify_uint64().

For unifying with strings use PL_unify_chars(). The string operations handle the input as unsigned chars regardless of the platform.

The documentation for PL_* functions have a “mode” indication on the term handles. “?” means it is unified against. “-” means it is assigned to (the handle is rebound to a new term) and “+” means the term is input to the function. This is a bit comparable to Prolog modes, except for “-”. A term_t bound to “5” with a “-” can simply be bound to “6”, i.e., we are talking about destructive assignment rather than unification.

(I asked about PL_error() as a more modern way of raising an exception - I was modifying some old code that created an error term and then called PL_raise_exception().)

For raising an error, PL_error() is not only not documented, but also doesn’t appear in the public headers and is (thus) not accessible on all platforms. Modern code mostly calls PL_type_error("mytype", Term) and related functions. Note that if the culprit is unbound these automatically raise an instantiation error rather than the indicated error. If possibly, use the PL_cvt_i_* or PL_get_*_ex() functions as they raise the exception for you.

BTW, some of the PL_documentation have extra “?” on the args, e.g.:
pl_unify_uint64(term_t ?t, uint64_t n))
PL_unify_chars(term_t ?t, int flags, size_t len, const char *chars)

Older discussions:

2 Likes

As of version 8.3.26 there is PL_get_uint64() and PL_get_uint64_ex(). For older versions you can use PL_cvt_i_uint64() which has the same signature and semantics as PL_get_uint64_ex().

Note that all these functions raise an instantiation error if the Prolog term is unbound, a type error if the Prolog term is not an integer, a domain error for the unsigned variants when the Prolog term is a negative integer and a representation error if the Prolog value doesn’t fit in an integer of the specified C size. If the conversion succeeds the result is reliable (no overflow, no loss of a sign).

2 Likes