When creating an R extension in C or C++, objects created in the compiled code need to be manually protected and unprotected from the garbage collector - e.g.:
SEXP some_func(SEXP inp)
{
SEXP some_vec = PROTECT(Rf_allocVector(REALSXP, 100));
// do something with 'some_vec' ...
UNPROTECT(1);
return some_vec;
}
Rcpp OTOH offers convenient classes which automatically handle the PROTECT
and UNPROTECT
calls, so one can safely do something like:
Rcpp::NumericVector some_func(SEXP inp)
{
Rcpp::NumericVector some_vec(100);
// do something with 'some_vec' ...
return some_vec;
}
Now, if I were to cast the Rcpp objects to generic SEXP, are they still auto protected? Example:
SEXP some_func(SEXP inp)
{
SEXP some_vec = Rcpp::NumericVector(100);
// do something with 'some_vec' ...
return some_vec;
}
Since some_vec
was allocated as a specialized NumericVector
but then casted to SEXP
, does it still undergo automatic PROTECT
/UNPROTECT
, or do I need to do it manually?
And what about casting the other way around? E.g. is this safe?
Rcpp::NumericVector some_func(SEXP inp)
{
Rcpp::NumericVector some_vec = Rf_allocVector(REALSXP, 100);
// do something with 'some_vec' ...
return some_vec;
}
Yes as the only interface that there is from R uses SEXP .Call(SEXP ...)
. So every Rcpp object automatically gets transformed (a lot with implicit conversion but also via Rcpp::wrap(...)
) and the protection is part of that.
You can easily verify that by for once creating a SEXP
manually without the protection layer and R will tell you in R CMD check
and/or crash.
From that you can conclude that Rcpp objects are correctly protected as this does not happen to them.