2013-09-27 14 views
12

Buduję pakiet w R z bardzo specyficznym algorytmem symulowanego wyżarzania dla mojego problemu, i mam wątpliwości dotyczące kodu C i SEXP, których nie byłem w stanie rozwiązać. Nie jestem ekspertem od R, pracowałem z tym tylko przez 3 tygodnie ... ale muszę to zrobić.R, .Call i struktury SEXP

O ile mi wiadomo, funkcja .Call w R przekazuje parametry jako struktura SEXP do C przez odniesienie (tj. Nie są one duplikowane). Czy mam rację? Co jeśli mam inną funkcję w C wywołaną z pierwszej funkcji w C, która potrzebuje tej struktury SEXP? (Zobacz przykład). Pytam, ponieważ jeden z tych parametrów jest dość duży i wykorzystuje dużo przestrzeni (10^7 ~ 10^18 podwójnych, chociaż nie używam ich wszystkich w każdej iteracji) i będę tę funkcję nazwać wiele razy , więc jeśli za każdym razem, gdy to nazywam, ten parametr zostanie zduplikowany, zabraknie mi pamięci.

MWe:

R wezwanie

MySimAn <- function(def_energy, i_pos, T0, Tfinal){ 
    ret <- .Call("CMySimAn",def_energy, i_pos, T0, Tfinal, seq0) 
    ret 
} 

funkcje C

double Energy(SEXP def_energy, SEXP seq0, int i0){ 
    int i; 
    double res=0; 
    for(i=0;i<INTEGER(GET_DIM(seq0))[0];i++){ 
    res += NUMERIC(def_energy)[i0+INTEGER(seq0)[i]]; 
    } 
    return(res); 
} 

SEXP CmySimAn(SEXP def_energy, SEXP i_pos, SEXP T0, SEXP Tfinal, SEXP seq0){ 
    SEXP = Ene; 
    PROTECT(Ene = NEW_NUMERIC(1)); 
    REAL(Ene)[0] = Energy(def_energy, seq0, INTEGER(i_pos)); 
    UNPROTECT(1); 
    return Ene; 
} 

Byłoby coś w tej pracy (kod w funkcji Energy nie sprawdza się tak może być źle)? Czy za każdym razem, gdy je nazywam, będę tworzył duplikat def_energy, czy to w R czy C? Bardzo ci dziękuje za pomoc.

Odpowiedz

8

Kod jest prawie (syntaktycznie) poprawny, jak zapisano, i nie ma kopiowania pamięci; argumenty przekazane do C z R powinny być traktowane jako "tylko do odczytu".

wspólny paradygmat zapisu warstwa pośrednia R/C, wszystkie funkcje zwane od tej warstwie czystego (non-R) C tak

double Energy(const double *def_energy, const int *seq0, int dim0, int i0) 
{ 
    int i; 
    double res=0; 
    for(i = 0; i < dim0; i++) { 
    res += def_energy[i0 + seq0[i]]; 
    } 
    return(res); 
} 

Zastosowanie const wymusić ukrytą zamówieniu, że wartości przekazywane z R nie powinny być zapisywane. Z R/C opakowaniu

SEXP CmySimAn(SEXP def_energy, SEXP i_pos, SEXP T0, SEXP Tfinal, SEXP seq0){ 
    double Ene = Energy(REAL(def_energy), INTEGER(seq0), INTEGER(GET_DIM(seq0)[0]), 
         INTEGER(i_pos)[0]); 
    return ScalarReal(Ene); 
} 

akcesora elementów numerycznej REAL() (użyto NUMERIC w energia). Twoje użycie PROTECT(...); REAL(Ene)[0] = ...; UNPROTECT(Ene); było poprawne.

+1

Dziękuję bardzo. Tak więc, wszystkie "wewnętrzne" funkcje C wywołane w czystym C. 'INTEGER (i_pos) [0]' jest, ponieważ 'INTEGER (i_pos)' jest wskaźnikiem, czy mam rację? –

+3

Tak, accessors 'INTEGER()', 'REAL()' zwracają wszystkie punkty. –