swipl-devel icon indicating copy to clipboard operation
swipl-devel copied to clipboard

Foreign interface for integers: PL_get_integer_ex() vs PL_cvt_i_int() etc.

Open kamahen opened this issue 3 years ago • 0 comments

There are two ways of getting an integer from a term (and throwing an exception if the term isn't an integer or is not representable as a C/C++ integer type): PL_get_integer_ex() PL_cvt_i_int()

Historically, the PL_cvt_i_*() functions got there to make the automatic wrapper generation using Quintus/SICStus style foreign function declarations easier. They also make the C++ API easier.

C++ (and C11 _Generic()) distinguishes integer "types" based on whether they have equivalent names, not on the underlying machine representation. So, for example, if a compiler has both long and long long as 64-bit integers, and if uint64_t is defined as unsigned long but size_t is defined as unsigned long long, then the compiler would conclude that uint64_t and size_t are different, even though they are both 64-bit unsigned. This means that when overloading functions with integers, an exhaustive list of the various integer types must be used. For an example of this, see the definition of PlTerm::integer() in SWI-cpp2.h. (If the wrong list of types is used, the compiler can generate strange "ambiguous conversion" messages; for example, not being able to figure out if the constant 1 is an int64_t or uint64_t..)

The PL_get_*_ex() (and underlying PL_get_*()) interface is missing a few C/C++ types. At some point, we should settle on one interface and deprecate the other, possibly adding a few missing choices. Another possibility is to use C11's _Generic() instead.

A slight complication is that C++ has a bool type but C doesn't (pl-incl.h defines bool as int).

kamahen avatar Oct 24 '22 18:10 kamahen