2013-07-08 30 views
5

Tôi đang sử dụng .Call lần đầu tiên. Tôi đã viết code đơn giản dưới đây, nơi tôi vượt qua một số nguyên và trả về một sexp (R):Lấy một số nguyên từ C sang R Lanugage bằng cách sử dụng .Call

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

Vì vậy, tôi gọi R CMD SHLIB mà tạo ra dll (không có vấn đề ở đây).

Khi chạy đoạn code dưới đây (R), tôi nhận được một câu trả lời khác nhau hơn 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: Có lẽ tôi đang nhận được giá trị của địa chỉ của biến con trỏ "a", thay vì giá trị của nó. Nhưng tôi không biết những gì tôi đang thiếu ở đây.

EDIT:

Sử dụng câu trả lời của tôi @JoshuaUlrich cố định mã và thêm nhiều tính năng hơn. Mã cố định là:

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

Khi gọi từ R bạn nhận được:

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 

Trả lời

1

định nghĩa hàm setInt bạn chấp nhận một int C như là đối số duy nhất của nó. Nhưng trong mã R của bạn, bạn đang chuyển một số INTSXP, chứ không phải là C int. Nói chung, các hàm C được gọi qua .Call chỉ nên chấp nhận SEXP làm đối số.

Vì vậy, thay đổi định nghĩa chức năng của bạn để:

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

Cũng lưu ý rằng có lẽ bạn nên đảm bảo aINTSXPlength(a)==1. Nếu length(a) > 1, bạn có thể thực hiện việc này:

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

Cảm ơn rất nhiều @JoshuaUlrich, chỉ một câu hỏi nữa. Tôi nên làm gì nếu 'a' là một vectơ các số nguyên và tôi sẽ trả về giá trị của [2] chẳng hạn. – MSardelich

+0

cảm ơn rất nhiều lần ... nó đóng các vòng của tôi ở đây ... – MSardelich

Các vấn đề liên quan