In the following code, object of type foo is created with a call to foo_new() and an external-pointer to the object is returned to R. Subsequent computations are performed by passing ptr_foo. The object is eventually freed with an explicit call to foo_free(foo *X). All computations are performed by libfoo.
Does the fact that ptr_foo was created mean that all other dynamically allocated fields within the foo object are automatically protected? Or, is it possible that fields such as "bar" may be swept away by the garbage collector?
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);
}
Thanks,
RT
It looks like your foo object is your own creation (not and SEXP). If so, it has nothing to do with R and is NOT garbage collected and therefore does not need to be/can't be protected. No one will look at it or its fields but you.
The bar object you put in it is also your own creation and not an R object (an SEXP) I assume. If it IS an SEXP or points to data within an SEXP then that data needs to be protected. A safer/easier way would then be to make a copy of the data in the SEXP.
When the ptr_foo object is no longer used by R and garbage collected, your ptr_foo_finalize function will be called to remove your foo object (and the bar part).