2

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?

lllllllllllll
  • 8,519
  • 9
  • 45
  • 80
  • 1
    Not quite the most inconsistent indentation ever, but getting there. – Jonathon Reinhart Jun 10 '14 at 03:32
  • @JonathonReinhart Sorry what..? I am not a English native speaker and I just don't get your pointer... :( – lllllllllllll Jun 10 '14 at 03:33
  • @computereasy he was politely explaining that your C code indentation is poor, making the C code more difficult to read than it needs to be. – lurker Jun 10 '14 at 10:59
  • What happens if you do, `arg[0] = Pl_Mk_Positive((PlLong)e);`? – lurker Jun 10 '14 at 17:03
  • @lurker No it stills can not work.. I am thinking that, as int in `Prolog` is 31bit, and `0xb` is `1011` while `0xf` is `1111`, is it something related to the 31bits of a integer..? – lllllllllllll Jun 10 '14 at 17:16
  • @lurker Hello lurker, I find a way to solve it and have tested it on simple c code as well as md5sum... it seems work well, even though I don't know why.. I am writing a answer below – lllllllllllll Jun 10 '14 at 17:53
  • In GNU prolog I think an integer is only 28 bits (signed or unsigned). `X = 0xfffffff.` will unify `X` with the value, but `X = 0x1fffffff.` will generate an overflow error. When you move into C, you're back at 32 bits, sign extended. – lurker Jun 10 '14 at 17:53
  • @lurker, Hello lurker, I am still stucked in this 28bit problem somehow, I posted it in this [question](http://stackoverflow.com/questions/24191587/how-to-use-a-long-int-in-gnu-prolog), could you give me some help on it..? THank you! – lllllllllllll Jun 12 '14 at 18:37

1 Answers1

0

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...

lllllllllllll
  • 8,519
  • 9
  • 45
  • 80