[R] .Call: is new attribute of protected object auto-protected

Douglas Bates bates at stat.wisc.edu
Sat Mar 6 14:28:00 CET 2004


"Vadim Ogranovich" <vograno at evafunds.com> writes:

> I have an SEXP obj in a C function called via .Call(). The obj is
> protected (in fact it is an argument to .Call and therefore
> automatically protected). If I set an attribute of obj does the
> attribute become protected too? Here is an example
>  
> SEXP foo(SEXP obj) {
>     SET_NAMES(obj, NEW_CHARACTER(3));  /* are names protected or not? */
> ...
> }

Yes.

I use that property extensively when I am writing code for the .Call
interface.  Take a look at the C code in the Matrix package for
r-devel (available in the src/contrib/1.9.0 directory on CRAN) and you
will see that in most functions that return an SEXP I create and
PROTECT the value to be returned then do all the other allocations
within SET_SLOT or setAttrib or SET_VECTOR_ELT.  This results in a lot of
what may be slightly strange looking code like 

   SEXP val = PROTECT(NEW_OBJECT(MAKE_CLASS("myclass")));
   int n;
   double *realslot;

   ...
   SET_SLOT(val, install("slotname"), allocVector(REALSXP, n));
   realslot = REAL(GET_SLOT(val, install("slotname")));
   ...   /* do something to the elements of the realslot vector here */
   UNPROTECT(1);
   return val;

It looks a bit strange because I am getting the slot immediately after
setting it.  (There are ways around this involving saving some
temporary results but I find them more confusing to read.)  The
important point is that I set the slot directly on allocating so that
the value of the allocation is protected and I don't have to PROTECT
and UNPROTECT it explicitly.  I find that having to keep track of how
many objects I have protected is a source of errors for me so I try to
ensure that I only PROTECT one object and do all allocations as
components of that object.  Usually I can manage to count up to 1
without making mistakes :-)




More information about the R-help mailing list