Search code examples
cpointersprologgnu-prolog

Weird situation in using a pointer as the argument for a C call Prolog Process


So basically my test is on 32bit x86 Linux, I use GNU Prolog 1.4.4

Here is the case, I have function ptr.c + pro.pl + interface.c

In the ptr.c, I use a wrapper to call a Prolog function in the pro.pl, then in the pro.pl, I use a prolog c interface to call a C function in interface.c, the argument is a C pointer.

I put some code here for each file:

ptr.c:

  int  C_wrapper_foo(int * e)                        
  {
    int  return_value; 

    int func;
    PlTerm arg[2];    //  function variable + return value insert
    PlBool res;

    func = Pl_Find_Atom("foo"); // function name insert

    Pl_Query_Begin(PL_FALSE);

    printf("%p\n", e);
    arg[0] = Pl_Mk_Integer((unsigned int)e);   // See, here I put pointer e as an arg

    arg[1] = Pl_Mk_Variable();

    res = Pl_Query_Call(func, 2, arg);          // insert (variable+return value)

    return_value = Pl_Rd_Integer(arg[1]);        // insert ()

    Pl_Query_End(PL_KEEP_FOR_PROLOG);

    return return_value;

  }

See, I put pointer e as the argument into Prolog.

Then in the Prolog code:

:- foreign(foo_c_instr(+integer)).

foo(E, FOO_RET) :-

foo_c_instr_0(E).

This is just a call into c function foo_c_instr in interface.c file.

PlBool foo_c_instr(int * e)
{
    printf("%p\n", e);
   return PL_TRUE;
}

The weird thing is that:

for example, the value of pointer e in the original ptr.c file is 0xbf9d4e4c, however, in the interface.c file, its value becomes 0xff9d4e4c!!!

This is so weird and I have debugged it for quite a while, but I just don't know what is wrong...

The interface I use to pass the pointer argument is:

arg[0] = Pl_Mk_Integer((unsigned int)e); 

I read the manual of gnu-prolog, and tried

arg[0] = Pl_Mk_Positive((unsigned int)e);
arg[0] = Pl_Mk_Integer((int)e);
arg[0] = Pl_Mk_Positive((int)e);

but it just can't work....

Could anyone give some help?


Solution

  • OK, so here is my ad-hoc solution:

    In the interface.c function, I do this mask on the pointer:

    PlBool foo_c_instr(int * e)
    {
       e = (unsigned int)e&0xbfffffff;
       printf("%p\n", e);
       return PL_TRUE;
    }
    

    then it works fine...