Search code examples
rrcpp

R: how to serialize C/C++ data that lives in the heap?


Suppose I want to wrap some C or C++ code which contains arrays or vectors that cannot be automatically mapped to R types by Rcpp, but which I need to pass to C/C++ functions that would output valid R objects. For example:

typedef union {
    size_t val_sizet;
    long double val_longdbl;
    } weird_struct
std::vector<weird_struct> an_unmappable_obj;
an_unmappable_obj.resize(2);
an_unmappable_obj[0].val_sizet = 1e20;
an_unmappable_obj[1].val_longdbl = 1.5 * 1e20;

Since this is a vector of a type that cannot be converted to any of R’s native types, I’m wondering how can I return and handle these objects inside R/Rcpp in such a way that the vector (or C array containing the same values) could be serialzed through saveRDS and its values restored after readRDS.

I guess one way of doing it would be through memcpy'ing the contents of the object to some C++ vector of a type that could be converted to Rcpp's 'NumericVector` or similar, then force-casting its first element to an array of the desired C types when it needs to be used, but I'm wondering if there's a better solution.


Solution

  • If you just want to save C++ data for later in the same session, the easiest way is to use external pointers. E.g.:

    // [[Rcpp::export]]
    Rcpp::XPtr< std::vector<double> > xptr_example() {
      std::vector<double> * x = new std::vector<double>(10);
      Rcpp::XPtr< std::vector<double> > p(x, true);
      return p;
    }
    

    If instead you still just want to serialize, there are lots of options but you will have to write some additional custom code.

    As you say, you could cast and memcpy into a R vector (use RawVector instead of NumericVector), but you have to be careful that your class has only "plain old data" and nothing special like pointers or file handlers.

    More formal serialization options and examples using Rcpp can be seen here and here.