Search code examples
crs-expressionr-extension

How to return a named VECSXP when writing R extensions


Recently I had a bug and when fixing it I wondered if it is possible to return a VECSXP (i.e. an R list type), where the elements are named. This c++ code:

SEXP do_bla() 
{
   int prtCnt = 0;
   SEXP a = PROTECT(allocMatrix(REALSXP, 5, 5));
   prtCnt++;
   SEXP b = PROTECT(allocVector(REALSXP, 5));
   prtCnt++;
   SEXP OS = PROTECT(allocVector(VECSXP, 2));
   prtCnt++;
   SET_VECTOR_ELT(OS, 0, a);
   SET_VECTOR_ELT(OS, 1, b);
   UNPROTECT(prtCnt);
   return OS;
}

would give me a list of two elements (matrix and vector) in R:

s <- .Call("do_bla", ....)

which can be indexed like this:

 s[[1]]; s[[2]]

What would I have to change to make this possible:

s$a; s$b

Or is this not possible?


Solution

  • See section 5.9.4 of Writing R Extensions. Allocate and populate a vector of names, and set the names attribute on the list.

    library(inline)
    named <- cfunction(signature(), '
        /* allocate and populate list */
        SEXP OS = PROTECT(allocVector(VECSXP, 2));
        SET_VECTOR_ELT(OS, 0, allocMatrix(REALSXP, 5, 5));
        SET_VECTOR_ELT(OS, 1, allocVector(REALSXP, 5));
    
        /* create names */
        SEXP nms = PROTECT(allocVector(STRSXP, 2));
        SET_STRING_ELT(nms, 0, mkChar("foo"));
        SET_STRING_ELT(nms, 1, mkChar("bar"));
    
        /* assign names to list */
        setAttrib(OS, R_NamesSymbol, nms);
    
        /* cleanup and return */
        UNPROTECT(2);
        return OS;')