2013-07-08 7 views
5

Używam .Call po raz pierwszy. napisałem prosty kod poniżej, gdzie przechodzą liczbę całkowitą i zwracają s-wyrażenie (R):Uzyskanie wektora całkowitego z C do R Lanugage przy użyciu .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; 
} 

ten sposób, że połączyć R CMD SHLIB który tworzy DLL (tutaj nie ma problemu).

Kiedy uruchomić kod poniżej (w R), otrzymuję odpowiedź inny niż 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: Prawdopodobnie jestem coraz wartość adresu zmiennej zmiennej "a", zamiast jej wartości. Ale nie wiem, czego tu brakuje.

EDIT:

Używanie odpowiedź @JoshuaUlrich Poprawiłem kod i dodano więcej funkcji. Stały kod jest:

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

Dzwoniąc z R otrzymasz:

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 

Odpowiedz

1

Twój setInt definicja funkcji akceptuje int C jako jedynego argumentu. Ale w twoim kodzie R podajesz INTSXP, a nie C int. Ogólnie funkcje C wywołane przez .Call powinny akceptować tylko SEXP jako argumenty.

więc zmienić definicję funkcji do:

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

Należy również pamiętać, że powinieneś upewnić a jest INTSXP i length(a)==1. Jeśli jest to length(a) > 1, możesz to zrobić:

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

Wielkie dzięki @JoshuaUlrich, proszę o jeszcze jedno pytanie. Co powinienem zrobić, jeśli "a" jest wektorem liczb całkowitych, a ja zwróciłbym na przykład wartość [2]. – MSardelich

+0

jeszcze raz dziękuję ... to zamyka tutaj moje pętle ... – MSardelich

Powiązane problemy