Dirk Eddelbuettel RInside: Easier embedding of R in C++ applications
 

Overview

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

History

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

Status

Version 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 make in the examples directory (and say make -f Makefile.win if on that other OS).

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.

Documentation

The examples/ directory provides some working examples. Auto-generated html documentation is available and included in the source distribution.

Download

A local archive is available here; there is also the CRAN page and SVN access is provided at R-Forge.

ChangeLog

2010-01-06  Dirk Eddelbuettel  

	* DESCRIPTION: Increase Version: to 0.2.1

	* src/RInside.cpp: Change startup so that interactive() comes out FALSE,
	  with that no longer call Rf_KillAllDevices(); as we may not have
	  had devices in the first place.

	* src/RInside.h: Logging helper protected by #ifndef as it is in Rcpp too

	* tools/unix2dos.r: Simple CRLF -> LF filter to nuke a Windows warning
	* src/Makefile.win: Employ unix2dos.r on two autogenerated files

	* DESCRIPTON: Set Depends: to R (>= 2.10.0) and Rcpp (>= 0.7.0)

	* src/*: Add full copyright headers and update copyright to 2010

2009-12-21  Dirk Eddelbuettel  

	* src/setenv.c: Minor error case fix for Windows
	* DESCRIPTON: Lower requirement for Rcpp to (>= 0.6.7)

2009-12-20  Dirk Eddelbuettel  

	* DESCRIPTION: Increase Version: to 0.2.0

	* src/setenv: Another small cleanup
	* inst/THANKS: Added Richard for all the initial help with Windows

	* src/RInside.cpp: Uncommented fpu_setup() for now

	* inst/doc/{html,man.latex}: Removed autogenerated doxygen files from
	  svn as they are too volatile, will remain in tarball as for Rcppccd

2009-12-16  Dirk Eddelbuettel  

	* src/tools/RInsideEnvVars.r: Deal with slashed on Windows platform

2009-12-15  Dirk Eddelbuettel  

	* DESCRIPTION: Remove 'OS_type: unix' as we now build and run on Windoze
	* src/Makefile.win: src/RInside.h, src/RInside.cpp: Added support for
	  building on Windows using the standard MinGW toolchain
	* src/setenv.c: Windows implementation of setenv() kindly provided by
	  Richard Holbrey during earlier attempts to build on Windows
        * inst/examples/Makefile.win: Similarly Makefile for Windows examples

2009-12-12  Dirk Eddelbuettel  

	* src/RInside.cpp: Destructor does a few additional things as per the
	  R_Cleanup example in section 8.1.2 on 'Setting R callbacks'
	* src/RIinside.h: Added simple logTxt() to log if defined and not otherwise.

2009-10-01  Dirk Eddelbuettel  

	* inst/examples/rinside_sample5.cpp: Another examples based on r-devel post

2009-09-29  Dirk Eddelbuettel  

	* inst/examples/rinside_sample4.cpp: New example based on new r-devel post

2009-09-25  Dirk Eddelbuettel  

	* DESCRIPTION: Increase Version: to 0.1.1
	
	* inst/THANKS: Added new file to say Thank You! to contributors

	* inst/examples/Makefile: set R_HOME variable to output of 'R RHOME',
	  use R_HOME to call R as R_HOME/bin/R, use R instead of Rscript,
	  query R about CXX and CPPFLAGS, general editing and overhaul

	* inst/examples/*.cpp: More consistent formatting using Emacs 'M-x untabify'

	* src/Makefile: Add $R_ARCH to install path for header files (thanks to
	  Jeff), call R with --vanilla switch (thanks to Jan), use R instead
	  of Rscript, general editing and overhaul

2009-09-19  Dirk Eddelbuettel  

	* DESCRIPTION: Increase Version: to 0.1.0, initial CRAN release

	* DESCRIPTION: Add 'OS_type: unix' to stop builds on Windows

	* DESCRIPTION: Add 'URL' pointer

	* doxyfile: Added Doxygen configuration file
	* inst/doc/: Added Doxygen generated html, latex, man files

	* inst/examples/Makefile: Also link against BLAS and LAPACK libs
	* inst/examples/rinside_sample3.cpp: New example using lm() and coef()

	* inst/examples/rinside_sample2.cpp: Added a try/catch block

	* src/Makefile: use $R_HOME/bin/R as per Kurt's reminder

2009-09-11  Dirk Eddelbuettel  

	* src/Makefile: Enhanced to now automatically regenerate the two
	  R-derived header files, and to also query R for directories which
	  should make the build more portable across different systems

	* src/MemBuf/cpp: Switch error message from fprintf to std::cerr
	  to avoid unncessary trouble with g++-4.4, with thanks to
	  Michael Kane for the heads-up

	* R/RInsidePaths.R: Added path helper functions called by Makefiles
	* NAMESPACE: Added (empty) file so we can call 'path helpers'

	* inst/examples/Makefile: Rewritten to no longer used fixed path
	  settings but rather query R, Rcpp and RInside

2009-07-28  Dirk Eddelbuettel  

	* inst/examples/rinside_sample2.cpp: Another simple example inspired
	  by a long thread on r-devel

2009-07-28  Dirk Eddelbuettel  

	* src/RInside.cpp: Added patch by Daniel F Schwarz to not set env
 	  vars with prior values (to e.g. allow non-standard R_HOME)

2009-07-19  Dirk Eddelbuettel  

	* src/MemBuf.cpp: Added one-line patch by Miguel Lechón in add()
	  method to correctly re-set pointer---with a bug Thanks! to Miguel

	* src/RInside.cpp: Added a few more assign() functions for STL
	  vectors of types double, int and string, as well as int matrices
	* src/RInside.*: Minor cleanups and edits

	* inst/examples/small_test*.cpp: Added two small examples to
	  illustrate and test the bug reported by Miguel Lechón
	* inst/examples/Makefile: generalised targets

2009-02-12  Dirk Eddelbuettel  

	* src/: Added new assign() method for strings, added 'quiet' Eval
 	  without return; made more function interfaces use references

	* man/: Added less-than-minimal RInside-package.Rd

	* inst/rinside_sample0: Added simple Hello World example

2009-02-10  Dirk Eddelbuettel  

	* Initial upload of version '0.0.1' to R-Forge SVN

Last modified: Wed Jan 6 21:59:07 CST 2010