Интерфейс R .call () и EXTPTRSXP: Понимание PROTECT / UNPROTECT с внешними объектами - PullRequest
5 голосов
/ 20 июля 2011

В следующем коде объект типа foo создается с вызовом foo_new (), а внешний указатель на объект возвращается в R. Последующие вычисления выполняются путем передачи ptr_foo. Объект в конце концов освобождается с явным вызовом foo_free (foo * X). Все вычисления выполняются libfoo.

Означает ли тот факт, что ptr_foo был создан, означает, что все другие динамически распределяемые поля в объекте foo автоматически защищены? Или, возможно, такие поля, как "bar", могут быть сметены сборщиком мусора?

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

Спасибо

RT

Ответы [ 2 ]

3 голосов
/ 21 июля 2011

Похоже, ваш объект foo - ваше собственное творение (а не SEXP).Если это так, он не имеет ничего общего с R и НЕ является сборщиком мусора, и поэтому не нуждается в защите.Никто не будет смотреть на него или его поля, кроме вас.

Вставленный в него объект bar - это также ваше собственное творение, а не объект R (SEXP), я полагаю.Если это SEXP или указывает на данные в SEXP, то эти данные должны быть защищены.Тогда более безопасным и простым способом было бы сделать копию данных в SEXP.

Когда объект ptr_foo больше не используется R и сборщик мусора, будет вызвана ваша функция ptr_foo_finalize для удаления вашего объекта foo(и часть бара).

1 голос
/ 20 июля 2011

Для начала, вы не должны использовать calloc() или malloc() для объектов R, руководство «Написание расширений R» довольно ясно об этом.

Во-вторых, каждое выделение получит свой собственный PROTECT all.

В-третьих, объекты внешнего указателя являются R-представлениями чего-то, созданного в другом месте (для канонического примера см. Пакет RODBC и его реализацию интерфейса БД). Я не думаю, что вы должны создавать объекты внешнего указателя изнутри.

...