Search code examples
cprologffignu-prolog

Why I can not store the address of one variable in "Prolog+C"?


So basically I want to call some C code from Prolog, and here is the code:

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;
   }
}

I use this to compile into binary format:

gplc -o sample sample.c sample.pl

The problem is that, after I run this code, the output is :

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

I don't understand why the fourth output is a new memory address, to my understanding, it should also be 0xbff2160c,

am I wrong? Could anyone give me some help?


Solution

  • There is a difference. In your function fun2, you get an integer on the stack, &val is the address of that integer.

    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  */
     ...
    }
    

    Also, ( I don't know any prolog, so I'm not sure what you do in that part ) if you are trying to pass pointers as int, it won't work. Generally, the size of pointers, and size of ints can be different. Using int to store a pointer is not going to work, e.g. on 64bit intels, usually int is a 32 bit integer, and a pointer is a 64 bit unsigned integer, that won't fit into 32 bits.