[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