2

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!

repeat
  • 18,496
  • 4
  • 54
  • 166

2 Answers2

3

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.

Community
  • 1
  • 1
Per Mildner
  • 10,469
  • 23
  • 30
  • 1
    No, there are no C-level convenience functions for throwing exceptions. We typically let our foreign functions return an integer error code that the calling Prolog code then use to decide whether an exception should be thrown. See the library source code for examples. – Per Mildner Mar 22 '15 at 19:32
  • The case when you throw an exception should be uncommon, so it should not matter for efficiency how you do it. Throwing exceptions from Prolog is much easier. On using "failure" as a result: a result code can convey more information than just success/failure. – Per Mildner Mar 25 '15 at 14:37
1

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] ...

mirta
  • 644
  • 10
  • 25
  • That's **not** it: With SICStus, `current_prolog_flag(bounded,F)` succeeds with `F = false`. – repeat Feb 12 '16 at 12:25