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)