2015-03-18 94 views
2

不断学习SICStus Prolog 4 FFI的C到C,我对https://sicstus.sics.se/sicstus/docs/latest4/html/sicstus.html/Foreign-Code-Examples.html#Foreign-Code-Examples中的示例谓词c1/2有一个具体的问题。SICStus Prolog 4:从Prolog传递整数到C

ex.pl包括行:

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

和ex.c包括下面的代码片段:

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

这适用于小整数:

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

它不适用于大整数:

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

如何正确(高效)地处理小和大整数? IIRC大整数不能作为“SP_integers”传递,所以我应该将这些值作为条件(“SP_term_ref”)传递,并进行适当的动态类型检查(可能随后进行数据提取)?请帮助!

回答

3

您是对的,外国型号integer对应于C型SP_integer,只能用于小型整数。对于任意大小的整数,您需要使用对应于C类型SP_term_ref的外部类型term,并使用SP_get_integer_bytes()函数来获取字节。有关详情,请参阅Passing arbitrary-sized integers from Prolog to C

由于SP_get_integer_bytes()适用于所有大小的整数,因此不需要进行显式动态类型检查,并且如果其参数不是整数,则会优雅地失败,并显示错误代码。

+1

不,没有用于抛出异常的C级便利功能。我们通常让我们的外部函数返回一个整数错误代码,然后调用Prolog代码来决定是否抛出异常。有关示例,请参阅库源代码。 – 2015-03-22 19:32:39

+0

你抛出一个异常的情况应该是不常见的,所以你应该怎么做都不重要。从Prolog抛出异常要容易得多。结果使用“失败”:结果代码可以传达更多信息,而不仅仅是成功/失败。 – 2015-03-25 14:37:47

1

我不确定,但也许是因为整数有一个特定的大小。基本整数在范围[-32767,+ 32767],长整数[-2147483647,+ 2147483647] ...

+0

这是**不是**:在SICStus中,'current_prolog_flag(有界,F)'用'F = false'成功。 – repeat 2016-02-12 12:25:36