使用.Call从C到R Lanugage获取整数向量

MSa*_*ich 5 c r

我第一次使用.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;
}
Run Code Online (Sandbox Code Playgroud)

因此,我调用R CMD SHLIB来创建dll(这里没问题).

当运行下面的代码(在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
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

从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
Run Code Online (Sandbox Code Playgroud)

Jos*_*ich 3

您的setInt函数定义接受 C int 作为其唯一参数。但在您的 R 代码中,您传递的是 a 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;
}
Run Code Online (Sandbox Code Playgroud)

另请注意,您可能应该确保aisINTSXPlength(a)==1。如果length(a) > 1,您可以这样做:

int *p_a;
p_a = INTEGER_POINTER(a);
p_myint[0] = p_a[1];  // get second element from a
Run Code Online (Sandbox Code Playgroud)