SICStus Prolog 4: Передача целых чисел из Пролога в C

Все еще изучая основы SICStus Prolog 4 FFI to C, у меня есть конкретный вопрос о примере предиката c1/2 в https://sicstus.sics.se/sicstus/docs/latest4/html./sicstus.html/Foreign-Code-Examples.html#Foreign-Code-Examples.

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») и выполнять подходящие проверки динамического типа (возможно, с последующим извлечением данных)? Помоги пожалуйста!


person repeat    schedule 18.03.2015    source источник


Ответы (2)


Вы правы, внешний тип integer соответствует типу C SP_integer и может использоваться только для небольших целых чисел. Для целых чисел произвольного размера вам нужно использовать внешний тип term, соответствующий типу C SP_term_ref, и использовать функцию SP_get_integer_bytes() для получения байтов. Подробнее об этом см. в разделе Передача целых чисел произвольного размера из Пролога в C.

Вам не нужна явная проверка динамического типа, так как SP_get_integer_bytes() работает для всех размеров целых чисел и корректно завершается с кодом ошибки, если его аргумент не является целым числом.

person Per Mildner    schedule 19.03.2015
comment
Нет, на уровне C нет вспомогательных функций для генерации исключений. Обычно мы позволяем нашим внешним функциям возвращать целочисленный код ошибки, который вызывающий код Пролога затем использует, чтобы решить, следует ли генерировать исключение. Примеры смотрите в исходном коде библиотеки. - person Per Mildner; 22.03.2015
comment
Случай, когда вы бросаете исключение, должен быть редкостью, поэтому для эффективности не должно иметь значения, как вы это делаете. Выбрасывать исключения из Пролога намного проще. Об использовании отказа как результата: код результата может нести больше информации, чем просто успех/неудача. - person Per Mildner; 25.03.2015

Я не уверен, но, возможно, это связано с тем, что целое число имеет определенный размер. Основное целое число находится в диапазоне [-32767,+32767], длинное целое число [-2147483647,+2147483647]...

person mirta    schedule 18.03.2015
comment
Это не: с SICStus current_prolog_flag(bounded,F) удается с F = false. - person repeat; 12.02.2016