2
votes

Still learning the ropes of the SICStus Prolog 4 FFI to C, I'm having a specific question about the example predicate c1/2 in https://sicstus.sics.se/sicstus/docs/latest4/html/sicstus.html/Foreign-Code-Examples.html#Foreign-Code-Examples.

ex.pl includes the line:

 foreign(c1,  c, c1(+integer, [-integer])).

and ex.c includes the following snippet:

 /* c1(+integer, [-integer]) */
 SP_integer c1(a)
 SP_integer a;
 {
    return(a+9);
 }

This works for small integers:

 | ?- c1(100,X).
 X = 109 ?
 yes
 | ?- c1(100000000000000,X).
 X = 100000000000009 ?
 yes

It does not work for big integers:

 | ?- c1(10000000000000000000000000,X).
 X = 1590897978359414793 ? 
 yes

How can I handle both small and big integers correctly (and efficiently)? IIRC big integers cannot be passed as "SP_integers", so should I pass these values as terms ("SP_term_ref") and do suitable dynamic type checks (possibly followed by data extraction)? Help, please!

2

2 Answers

3
votes

You are correct, the foreign type integer corresponds to the C type SP_integer and can only be used for small integers. For arbitrary sized integers you need to use the foreign type term, corresponding to the C type SP_term_ref, and use the SP_get_integer_bytes() function to get the bytes. See Passing arbitrary-sized integers from Prolog to C for more on this.

You do not need an explicit dynamic type check since SP_get_integer_bytes() works for all sizes of integers and gracefully fails with an error code if its argument is not an integer.

1
votes

I'm not sure, but maybe it is because integer has a specific size. Basic integer is in range [−32767,+32767], long integer [−2147483647,+2147483647] ...