2013-07-08 40 views
5

我第一次使用.Call。 我寫下面的簡單代碼,其中我傳遞一個整數並返回一個SEXP(以R):使用.Call獲取C到R的整數向量Lanugage

#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; 
} 

因此,我請ř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 

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 

回答

1

setInt函數定義接受一個C INT作爲其唯一參數。但在您的R代碼中,您傳遞的是INTSXP,而不是C int。通常,通過.Call調用的C函數應該只接受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; 
} 

另外請注意,你應該確保aINTSXPlength(a)==1。如果length(a) > 1,你可以這樣做:

int *p_a; 
p_a = INTEGER_POINTER(a); 
p_myint[0] = p_a[1]; // get second element from a 
+0

非常感謝@JoshuaUlrich,只有一個問題吧。如果'a'是一個整數向量,我應該怎麼做,我會返回例如[2]的值。 – MSardelich

+0

再次感謝...它在這裏關閉我的循環... – MSardelich