|
|
RInside: Easier embedding of R in C++ applications | |||||
|
Bio Code rprotobuf rinside rcpp rpostgresql rdieharder littler random digest rquantlib beancounter smtm yahooquote octave-mt octave-pg Linux Quantian About Blog |
OverviewThe RInside package provides C++ classes that make it easier to embed R in C++ code -- on either Linux, OS X or Windows (but see below for the latter). Embedding R is described first and foremost in the 'R Extensions' manual in the core R sources. It describes how to embed R --- but it does not make for easy reading as they are many little details to take care of. Viewed from another angle, this is one of the standard motivations for abstraction and embedding (of both the logic and the little details) in dedicated (C++) classes. Presto -- that is exactly what RInside does. Consider this overly complicated 'hello, world' program in six lines, included as rinside_sample0.cpp in the sources. It provides an instance of an embedded R interpreter, an assignment and an evaluation in just a handful of lines:// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; -*- // // Simple example showing an overly complicated way to do the standard 'hello, world' example // // Copyright (C) 2009 - 2010 Dirk Eddelbuettel and GPL'ed #include "RInside.h" // for the embedded R via RInside #include "Rcpp.h" // for the R / Cpp interface used for transfer int main(int argc, char *argv[]) { RInside R(argc, argv); // create an embedded R instance std::string txt = "Hello, world!\n";// assign a standard C++ string to 'txt' R.assign( txt, "txt"); // assign string var to R variable 'txt' std::string evalstr = "cat(txt)"; R.parseEvalQ(evalstr); // eval the init string, ignoring any returns exit(0); } While this example is contrived, real-world uses are in the (possibly repeated) calling of data preparation, scrubbing, pre- or post-processing in the context of a C++ program. So rather than writing the data you may have out to file, calling R, parsing results back in -- and worse, doing this over and over -- you can start R once, and pass data structures to it, call functions you may have preloaded and get condensed results back. A lightly more interesting example is // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; -*- // // Simple example with data in C++ that is passed to R, processed and a result is extracted // // Copyright (C) 2009 - 2010 Dirk Eddelbuettel and GPL'ed #include "RInside.h" // for the embedded R via RInside #include "Rcpp.h" // for the R / Cpp interface used for transfer std::vector< std::vector< double > > createMatrix(const int n) { // simple STL matrix content generator std::vector< std::vector< double > > mat; for (int i=0; i<n; i++) { std::vector<double> row; for (int j=0; j<n; j++) { row.push_back((i*10+j)); } mat.push_back(row); } return(mat); } int main(int argc, char *argv[]) { const int mdim = 4; std::string evalstr = "\ cat('Running ls()\n'); print(ls()); \ cat('Showing M\n'); print(M); \ cat('Showing colSums()\n'); Z <- colSums(M); print(Z); \ Z"; // returns Z RInside R(argc, argv); SEXP ans; // create and fill a sample data Matrix std::vector< std::vector< double > > myMatrix = createMatrix(mdim); R.assign( myMatrix, "M"); // assign STL matrix to R's 'M' var R.parseEval(evalstr, ans); // eval the init string -- Z is now in ans RcppVector<double> vec(ans); // now vec contains Z via ans std::vector<double> v = vec.stlVector(); // convert RcppVector to STL vector // We could also do the assignment in one line: // vector<double> v = RcppVector<double>(ans).stlVector(); // show the result for (unsigned int i=0; i< v.size(); i++) { std::cout << "In C++ element " << i << " is " << v[i] << std::endl; } exit(0); }More examples will be added over time. In fact, as of version 0.2.0, the examples/ directory of the installed package (and hence inst/examples/ in the sources) now contains six examples as well as two quasi-regression tests.
HistoryRInside owes its basic structure to littler, the first-ever R scripting front-end by Jeff Horner and myself. RInside, just like littler, owes a lot to the tricks Jeff learned about embedding R via his Rapache project. However, RInside is a fresh C++ version of these ideas.
StatusVersion 0.2.1 should build and install on just about any Linux and OS X system, and even on Windows machines that have the Rtools compiled by Duncan Murdoch as detailed in the The Windows Toolset appendix to the R Installation manual. Do not, I repeat, do not report an error if you fail to build this with another compiler as this is not supported.
A total of six complete examples are provided, as well as two test programs
that triggered earlier bugs. These can serve as simple examples for your own
programs. After installation, just say The interface is still somewhat bare bones and I need to add more assignment operators for different types and generalise the build process. At least Rcpp provides a full set of converters from the different R types to C++. RInside works particularly well with the Rcpp package for interfacing R and C++ and shown by the examples in the RInside distribution.
DocumentationThe examples/ directory provides some working examples. Auto-generated html documentation is available and included in the source distribution.
DownloadA local archive is available here; there is also the CRAN page and SVN access is provided at R-Forge.ChangeLog2010-01-06 Dirk Eddelbuettel |
|||||