From mitomaster at gmail.com  Mon Dec 16 04:11:08 2013
From: mitomaster at gmail.com (Krzysztof Mlynarczyk)
Date: Mon, 16 Dec 2013 04:11:08 +0100
Subject: [Rd] External pointers and changing SEXPTYPE
Message-ID: <CAPxYnfpR=0bVy2m2214f7765MBDmGupFs6=VB7L5K7cH35Z5Ng@mail.gmail.com>

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



[Rd] External pointers and changing SEXPTYPE
Krzysztof Mlynarczyk