5

初めて .Call を使用しています。以下の簡単なコードを書きました。ここでは、整数を渡し、SEXP を (R に) 返します。

#include <R.h>
#include <Rdefines.h>

SEXP setInt(int *a) {
   SEXP myint;
   int *p_myint;
   int len = 5;

   PROTECT(myint = NEW_INTEGER(len)); // Allocating storage space
   p_myint = INTEGER_POINTER(myint); // ponit to SEXP object

   p_myint[0] = *a;

   UNPROTECT(1);
   return myint;
}

したがって、dll を作成する R CMD SHLIB を呼び出します (ここでは問題ありません)。

以下のコードを (R で) 実行すると、c(100,0,0,0,0)とは異なる答えが得られます。

> dyn.load(file.path(path.dll,paste0("useC", .Platform$dynlib.ext)))
> a<-100
> out<- .Call("setInt",as.integer(a))
> out
[1] 536870925         0         0         0         0

PS: おそらく、ポインター変数 "a" の値ではなく、そのアドレスの値を取得しています。しかし、ここで何が欠けているのかわかりません。

編集:

@JoshuaUlrich の回答を使用して、コードを修正し、さらに機能を追加しました。固定コードは次のとおりです。

SEXP setInt(SEXP a,SEXP pos) {
   SEXP myint;
   int *p_a;
   int *p_myint;
   int len = 5;

   PROTECT(myint = NEW_INTEGER(len)); // Allocate storage space, with default 5 zeroes
   p_myint = INTEGER_POINTER(myint); // ponit to SEXP object

   p_a = INTEGER_POINTER(a);

   p_myint[0] = p_a[(asInteger(pos)-1)];  // get the element at pos

   UNPROTECT(1);
   return myint;
}

R から呼び出すと、次のようになります。

a<-c(100,200,300)
pos<-1
out<- .Call("setInt",as.integer(a),as.integer(pos))

> out
[1] 100 0 0 0 0

pos<-2
out<- .Call("setInt",as.integer(a),as.integer(pos))

> out
[1] 200 0 0 0 0
4

1 に答える 1

3

関数setInt定義は、C int を唯一の引数として受け入れます。しかし、R コードでINTSXPは、C の int ではなく を渡しています。一般に、経由で呼び出される C 関数は.Call、SEXP のみを引数として受け入れる必要があります。

したがって、関数定義を次のように変更します。

SEXP setInt(SEXP a) {
   SEXP myint;
   int *p_myint;
   int len = 5;

   PROTECT(myint = NEW_INTEGER(len)); // Allocating storage space
   p_myint = INTEGER_POINTER(myint); // ponit to SEXP object

   p_myint[0] = AS_INTEGER(a);

   UNPROTECT(1);
   return myint;
}

aまた、おそらくisINTSXPとであることを確認する必要があることに注意してくださいlength(a)==1。場合length(a) > 1、これを行うことができます:

int *p_a;
p_a = INTEGER_POINTER(a);
p_myint[0] = p_a[1];  // get second element from a
于 2013-07-08T14:34:51.950 に答える