Search code examples
rcpp

Rcpp: are objects safely PROTECTed if I cast to/from SEXP?


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;
}

Solution

  • 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.