Почему я не могу хранить адрес одной переменной в Prolog+C?

Итак, в основном я хочу вызвать некоторый код C из Prolog, и вот код:

Пролог:

:-foreign(fun1(+integer,-integer)).
:-foreign(fun2(+integer,-integer)). 

% p = b;
testfuna(Var, Val) :- fun1(Val, Var).
% p = &b;
testfunb(Var, Val) :- fun2(Val, Var).

main :-
A is 1,
testfuna(A, P),
write(P),
testfunb(A, P),
write(P),

% print out

write(A), nl.

C:

#include <gprolog.h>
#include <string.h>

PlBool fun1(int ptr, int* res){
    *res = ptr;
    printf("%d\n", *res);
    if(res==NULL){
      return PL_FALSE;
    }else{
      return PL_TRUE;
    }
}

PlBool fun2(int val, int* res){
   *res = &val;
   printf("%p\n", *res);
   if(res==NULL){
      return PL_FALSE;
   }else{
      return PL_TRUE;
   }
}

Я использую это для компиляции в двоичный формат:

gplc -o sample sample.c sample.pl

Проблема в том, что после запуска этого кода вывод:

  1    <--- right
  1    <--- match, right!
  0xbff2160c       <-- it is on the stack
  -911860     <--- why?              

Я не понимаю, почему четвертый вывод - это новый адрес памяти, в моем понимании он тоже должен быть 0xbff2160c,

я ошибся? Может ли кто-нибудь помочь мне?


person lllllllllllll    schedule 12.04.2014    source источник


Ответы (2)


Есть разница. В вашей функции fun2 вы получаете целое число в стеке, &val — это адрес этого целого числа.

PlBool fun1(int ptr, int* res){
 *res = ptr;  /* ptr is what you got from prolog */
 ...
}

PlBool fun2(int val, int* res){
 *res = &val; /* val is a copy on the stack here, */
 /* you don't use at all what you got from prolog, only the address */
 /* of a local copy in the stack  */
 ...
}

Кроме того (я не знаю никакого пролога, поэтому я не уверен, что вы делаете в этой части), если вы пытаетесь передать указатели как int, это не сработает. Как правило, размер указателей и размер целых чисел могут быть разными. Использование int для хранения pointer не сработает, например. на 64-битных интелах обычно int - это 32-битное целое число, а указатель - это 64-битное целое число без знака, которое не помещается в 32-битное число.

person Gábor Buella    schedule 12.04.2014

Просто предположение, но это предел размера целого числа, передаваемого в пролог?

Я не знаю пролог gnu, но в прологе swi есть специальный вызов PL_get_pointer и PL_put_pointer специально для обработки адресов. PL_get_integer и PL_put_integer не будут работать. Поищите эквивалент в gnu.. возможно, адрес искажается.

Изменить: возможно, вам просто придется изменить его с int на long или double... что-то в этом роде.

person magus    schedule 12.04.2014