2011-07-20 5 views
5

W poniższym kodzie tworzony jest obiekt typu foo z wywołaniem foo_new(), a zewnętrzny wskaźnik do obiektu jest zwracany do R Kolejne obliczenia są wykonywane przez przekazanie ptr_foo. Obiekt jest ostatecznie zwalniany przez jawne wywołanie foo_free (foo * X). Wszystkie obliczenia są wykonywane przez libfoo.Interfejs R .call() i EXTPTRSXP: Opis PROTECT/UNPROTECT z zewnętrznie przydzielonymi obiektami

Czy fakt, że ptr_foo zostało utworzone, oznacza, że ​​wszystkie inne dynamicznie przydzielane pola w obiekcie foo są automatycznie chronione? Czy jest możliwe, że pola takie jak "bar" mogą zostać usunięte przez garbage collectora?

SEXP foo_new (SEXP n) { 
    SEXP ptr_foo; 
    foo *X = (foo*) foo_new(1, sizeof(foo)); 
    //foo is protected from garbage collection 
    assert(X); 
    X->bar = (int*) foo_add_bar(INTEGER_VALUE(n)); 
    //Is bar protected from garbage collection? 
    assert(X->bar); 
    PROTECT(ptr_foo = R_MakeExternalPtr(X, install("extptr_foo"), R_NilValue)); 
    R_RegisterCFinalizerEx(ptr_foo, ptr_foo_finalize, 1); 
    UNPROTECT(1); 
    return (ptr_foo); 
} 

Dzięki

RT

Odpowiedz

3

Wygląda na to, że twój obiekt typu foo jest Twoim własnym dziełem (nie SEXP). Jeśli tak, to nie ma to nic wspólnego z R i NIE jest zbiorem śmieci i dlatego nie musi być/nie może być chronione. Nikt nie będzie patrzył na to ani na pola, ale na ciebie.

Obiekt pręta, który w nim umieszczasz, jest także twoim własnym stworzeniem, a nie obiektem R (SEXP), który zakładam. Jeśli jest to SEXP lub wskazuje dane w obrębie SEXP, to dane te muszą być chronione. Bezpieczniejszym/łatwiejszym sposobem byłoby wówczas wykonanie kopii danych w SEXP.

Gdy obiekt ptr_foo nie jest już używany przez R i śmieci zebrane, twoja funkcja ptr_foo_finalize zostanie wywołana, aby usunąć twój obiekt foo (i część pręta).

+0

Dzięki Tommy. Tego właśnie oczekiwałem. Jak wskazujesz, cała wymiana danych między R i libfoo odbywa się poprzez kopiowanie SEXP do i na zewnątrz. Wszystkie obiekty przydzielone przez bibliotekę są zwalniane przez wywołanie foo_free(). – user151410

1

Na początek, nie powinni używać calloc() lub malloc() obiektów R, "Writing R Extensions" Instrukcja jest całkiem jasne w tej sprawie.

Po drugie, każda alokacja ma swój własny CHRONIĆ wszystko.

Po trzecie, zewnętrzne obiekty wskaźnikowe to reprezentacje R czegoś utworzonego gdzie indziej (na przykład kanoniczny, patrz pakiet RODBC i jego implementacja interfejsu DB). Nie sądzę, że powinieneś tworzyć zewnętrzne obiekty wskaźnikowe od wewnątrz.

+0

Dzięki Dirk, zredagowałem mój oryginalny kod. Użyłem 'calloc()', aby prosty przykład był prosty. Tworzenie, niszczenie i obliczenia obejmujące 'foo' i' bar' są wykonywane przez wywołania funkcji w 'libfoo'. Dziękujemy za wskaźnik do pakietu RODBC. – user151410