Hi, 

One solution to protect an object from the GC is to use the R_PreserveObject 
and R_ReleaseObject functions. 

This way, you are not subject to the stack that PROTECT, UNPROTECT, 
UNPROTECT_PTR uses. 

Using R_PreserveObject and R_ReleaseObject is one of the best things that has 
ever happened to Rcpp. 

Romain

Le 16 déc. 2013 à 12:07, Krzysztof Mlynarczyk <mitomas...@gmail.com> a écrit :

> As far as I understood the documentation, external pointer should be
> automatically protected from gc when returned to environment. The
> solution you've just suggested would cause stack imbalance.
> Recently I've been thinking of encapsulating the pointer into a nice
> object using Rcpp. This sounds better that telling people to have fun
> with an external pointer itself.
> 
> KM
> 
> 2013/12/16 peter dalgaard <pda...@gmail.com>:
>> Offhand, I'd say that if "all protects get unprotected before return"
>> mydata->ans is not protected against garbage collection, and thus very 
>> likely collected and reused. If mydata is created by Calloc, the GC has no 
>> way of knowing that it might have pointers to things that are intended to 
>> persist.
>> 
>> I haven't played with external pointers for a while, but I'd expect that 
>> you'd need to retain a PROTECT on mydata->ans, and then UNPROTECT_PTR or so 
>> in the finalizer.
>> 
>> -pd
>> 
>> On 16 Dec 2013, at 04:11 , Krzysztof Mlynarczyk <mitomas...@gmail.com> wrote:
>> 
>>> Dear Developers,
>>> 
>>> 
>>> I've been struggling through writing R extension in C. I've been using
>>> an external pointer to store my data (please see sample below). I
>>> encountered a very weird erroneous behaviour: when I tried to use my
>>> external pointer to a structure holding several types of data,
>>> including SEXPs, I discovered that SEXPs change their types between
>>> returning from initialization function and another one that uses the
>>> pointer.
>>> 
>>> sample R code:
>>> 
>>> # initializing
>>> a <- init_my_ptr(fname)
>>> 
>>> # reading more data: error!
>>> df <- read_my_data(a)
>>> 
>>> data structure in C:
>>> typedef struct {
>>> SEXP ans, ans_nms, R_z, R_a, R_b, R_c;
>>> FTYPE *datafile;
>>> char *fname;
>>> float *a, *b, *c;
>>> int f_type;
>>> float t, p, l;
>>> int st, na, result, bFlags;
>>> XXX z;
>>> } my_data_ptr;
>>> 
>>> // In a C function initializing the external pointer:
>>> my_data_ptr *mydata = Calloc( 1, my_data_ptr ) ;
>>> SEXP Rdata;
>>> PROTECT(Rdata = R_MakeExternalPtr( mydata, R_fname, R_NilValue ));
>>> ...
>>> mydata->a = Calloc(mydata->na, float);
>>> // same for b and c
>>> // initializing names so that I could use e.g. df$a where df is
>>> returned by read_my_data()
>>> PROTECT(mydata->ans_nms = Rf_allocVector(STRSXP, efldNR ));
>>> for( ix = 0; ix < efldNR; ix++ )
>>>   SET_STRING_ELT(mydata->ans_nms, ix, mkChar(vnames[ix]));
>>> 
>>> // later I bind values of non-R variables from my data structure to a
>>> proper vector
>>> PROTECT(mydata->ans = Rf_allocVector(VECSXP, efldNR ));
>>> 
>>> Rf_setAttrib(mydata->ans, R_NamesSymbol, mytraj->ans_nms);
>>> SET_VECTOR_ELT(mydata->ans, 0,      mydata->R_a );
>>> SET_VECTOR_ELT(mydata->ans, 1,      mydata->R_b );
>>> ...
>>> // all protects get unprotected before return
>>> // finalizer is registered as well
>>> return Rdata;
>>> 
>>> Later on in read_my_data() I read the pointer:
>>> my_data_ptr *mydata = (my_data_ptr*) R_ExternalPtrAddr(Rdata);
>>> 
>>> // and REAL(mydata->R_a) yields error since TYPEOF(mydata->R_a) is not
>>> REALSXP as it should be but RAWSXP for some reason // (sometimes it's
>>> STRSXP or INTSXP while it should always be REALSXP)
>>> // The error message says:
>>> // REAL() can only be applied to a 'numeric', not a 'raw'
>>> 
>>> // mydata->ans is the object returned to R where all the data is made
>>> available to R user:
>>> return mydata->ans;
>>> 
>>> // end of example code
>>> 
>>> Could you please point the possible reasons for the error along with
>>> the ways of fixing this issue? I've been trying in R-3.0.2, 3.0.1 and
>>> even 2.15 -- the problem happens in each of them.
>>> 
>>> 
>>> Regards,
>>> Christopher
>>> 
>>> ______________________________________________
>>> R-devel@r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>> 
>> --
>> Peter Dalgaard, Professor
>> Center for Statistics, Copenhagen Business School
>> Solbjerg Plads 3, 2000 Frederiksberg, Denmark
>> Phone: (+45)38153501
>> Email: pd....@cbs.dk  Priv: pda...@gmail.com
>> 
> 
> ______________________________________________
> R-devel@r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to