Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R .call() interface and EXTPTRSXP: Understanding PROTECT/UNPROTECT with externally allocated objects

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

like image 360
user151410 Avatar asked Jul 20 '11 04:07

user151410


2 Answers

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).

like image 54
Tommy Avatar answered Nov 17 '22 22:11

Tommy


For starters, you are not supposed to use calloc() or malloc() for R objects, the "Writing R Extensions" manual is pretty clear on that.

Second, each allocation would get its own PROTECT all.

Third, external pointer objects are R representations of something created elsewhere (for a canonical example , see the RODBC package and its implementation of DB interface). I don't think you're supposed to create external pointer objects from within.

like image 27
Dirk Eddelbuettel Avatar answered Nov 17 '22 21:11

Dirk Eddelbuettel