An enormous amount of R packages exists, providing all sorts of functionality. At some point one might require additional features, available through external libraries, or performance of the program might be an issue. Especially in the case of speeding up the program C++ is a natural choice, as it easily interfaces with R. Integrating C++ code into an R project is relatively straightforward – the easiest way being the Rcpp package. I recommend having a look at the package’s vignettes if you are interest in further details on Rcpp and its capabilities.
What I would like to present here is a minimal working example of a C++ library callable from R. The use case is as follows: Calling functionality in the C++ library from R results in the creation of C++ objects on the program’s heap. Once the C++ call is finished, we may continue working in our R session running further C++ calls. Usually the objects of our previous C++ call will no longer be available. The program architecture presented here makes all objects created in C++ available to the R session via string handles.
In a first step we have to create a new R project. The project comes with some default test code which we later replace by our own C++ code. This is how creating an R package is done:
File > New Project. The following menu opens. Choose New Directory.
R Package item.
Package w/ Rcpp in the upper left drop-down, specify a package name in the upper right text box (CppLibrary in my case) and make sure that the package location is correctly specified in the bottom text box.
Create Project to finish. When being ask, allow installation of build tools, i.e. Rtools. The build tools come with all default compilers such as gcc/g++ in our case. Your result should look somewhat similar to the below screenshot.
Install and Restart in the Build tab.R/hello.R and src/rcpp_hello.cpp as well as everything in the man subfolder. We will add our own sources soon.Makevars with the following content to the package’s src folder.
PKG_CPPFLAGS = `$(R_HOME)/bin/Rscript -e "Rcpp:::CxxFlags()"`
PKG_LIBS = `$(R_HOME)/bin/Rscript -e "Rcpp:::LdFlags()"`
PKG_CXXFLAGS += -std=c++11
gsl add the following two lines to Makevars:
PKG_LIBS += -I/usr/include
PKG_LIBS += -L/usr/lib64 -lgsl -lgslcblas –lm
Let us introduce an object ObjectFactory by creating a source ObjectFactory.h with the below content in the package’s src subdirectory. The ObjectFactory will serve as both an instantiation helper and an object register to all classes which we want to be accessible multiple times from R. I will not go into all details but let me draw your attention to the following key aspects:
ObjectLibrary a class has to implement a constructor taking a string handle argument. This allows calling Object_Ptr get(const std::string& handle) which returns the respective instance of our target class if it exists and otherwise creates a new one.ObjectFactory for potentially arbitrary classes as long as they implement a handle constructor. Thus ObjectFactory is implemented as a template <class T>.ObjectFactory implements the so called singleton design pattern which ensures that at runtime all instances of class T will be handled by a single ObjectFactory. Therefore, the default constructor is made private and the copy constructor and assign operator are deleted. Instead, the ObjectFactory can be instantiated by calling getInstance(). For more details on the singleton design pattern specifically (Chapter 5) and design patterns in general I highly recommend checking "Head First: Design Patterns" by O’Reilly. Note that the book is Java based but an excellent read anyways.m_storage keeps track of all target class instances and makes them available through their respective string handle.
#ifndef OBJECT_FACTORY_
#define OBJECT_FACTORY_
#include <map>
#include <memory>
#include <string>
namespace OBJ {
template <class T>
class ObjectFactory;
template <class T>
ObjectFactory<T>& getFactory() {
return ObjectFactory<T>::getInstance();
}
template <class T>
class ObjectFactory {
public:
typedef std::shared_ptr<T> Object_Ptr;
private:
std::map<std::string, Object_Ptr> m_storage;
ObjectFactory() {}
public:
static ObjectFactory& getInstance() {
static ObjectFactory instance;
return instance;
}
ObjectFactory(ObjectFactory const&) = delete;
void operator=(ObjectFactory const&) = delete;
Object_Ptr get(const std::string& handle) {
auto it = m_storage.find(handle);
if (it == m_storage.end()) {
Object_Ptr instance = std::make_shared<T>(handle);
m_storage.emplace(handle, instance);
return instance;
} else {
return it->second;
}
}
};
}
#endif
To test our simple library, create two files Test.h and testFunctions.cpp with the below code in the src subdirectory. Test.h introduces a class Incrementor which initialises a counter at 0 and allows to inc() that counter by one. The counter’s current value can be received by calling getCounter(). The second file testFunctions.cpp provides a simple function interface of Incrementor to R. Note that this is overly simplistic as all three R callable functions could be abstracted into a generic function interface.
Check the code of initIncrementor for instance to experience ObjectFactory in action. The string handle is passed from R and an instance of Incrementor is stored in ObjectFactory’s map m_storage. When later calling incIncrementor with the same handle the very same Incrementor instance is used to increment its counter. A short note on Rcpp: // [[Rcpp::export]] tells the C++ compiler to create an R callable version of the subsequent function, i.e. converting the return type (e.g. bool) and the function’s parameters (e.g. std::string) to something R can work with internally. In fact, that something is a so called SEXP which is short for S expression.
#ifndef TEST_
#define TEST_
#include <string>
namespace TST {
class Incrementor {
private:
int m_counter;
std::string m_handle;
public:
Incrementor(const std::string& handle) {
m_counter = 0;
m_handle = handle;
}
void inc() {
++m_counter;
}
int getCounter() {
return m_counter;
}
};
}
#endif
#include "ObjectFactory.h"
#include "Test.h"
#include <Rcpp.h>
#include <memory>
#include <string>
using namespace Rcpp;
// [[Rcpp::export]]
bool initIncrementor(const std::string& handle) {
auto i = OBJ::getFactory<TST::Incrementor>().get(handle);
return (i ? true : false);
}
// [[Rcpp::export]]
bool incIncrementor(const std::string& handle) {
auto i = OBJ::getFactory<TST::Incrementor>().get(handle);
i->inc();
return (i ? true : false);
}
// [[Rcpp::export]]
int getCounter(const std::string& handle) {
return OBJ::getFactory<TST::Incrementor>().get(handle)->getCounter();
}
Finally, rebuild the package and execute the following R code line by line. This what the result should look like.
#
# test ObjectFactory
#
hdl <- "my_handle"
initIncrementor(hdl)
getCounter(hdl)
incIncrementor(hdl)
getCounter(hdl)