1

基本的に、Prolog からいくつかの C コードを呼び出したいと思います。コードは次のとおりです。

プロローグ:

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

子:

#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?              

4 番目の出力が新しいメモリ アドレスである理由がわかりません。私の理解では、それも0xbff2160cである必要があります。

私が間違っている?誰か助けてくれませんか?

4

2 に答える 2

1

違いがあります。あなたの関数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 のサイズは異なる場合があります。aを使用intして格納することpointerはできません。たとえば、64 ビットのインテルでは、通常intは 32 ビットの整数であり、ポインタは 64 ビットの符号なし整数であり、32 ビットに収まりません。

于 2014-04-12T19:28:45.417 に答える
1

推測ですが、 prolog に渡される整数のサイズの制限ですか?

私は gnu プロローグを知りませんが、swi プロローグには、アドレスを処理するための特別な呼び出し PL_get_pointer と PL_put_pointer があります.. PL_get_integer と PL_put_integer は機能しません。gnu で同等のものを探してください。アドレスが破損している可能性があります。

編集:intからlong、またはdoubleに変更する必要がある可能性があります..そのようなもの。

于 2014-04-12T19:36:29.933 に答える