OU blog

Personal Blogs

Terence Wright

How to link R with C++

Visible to anyone in the world
Edited by Terence Wright, Wednesday, 16 Apr 2014, 06:58

I had to call a C++ function from a piece of R code. The C++ function created an object that was part of a big hierarchy of objects which did a big simulation before returning the result to R.  This is just a really, really, really simple way of doing it that can be used straight away without having to understand the innards of R.

I thought originally about using the library Rcpp, however this does not seem to take compiled code, from say VS2008. What it seems to do, and maybe I am wrong about this, is to compile C++ code inside the R environment and then run it.

What I wanted to do is to build a big project in VS2008 and then call it from R.

Firstly then I had to build my project as a dynamic link library or dll. This is a prerequisite to this method. In the dll you need to export the c++ function:

extern "C" __declspec(dllexport) void add(double* data){

data[2] = data[0] + data[1];

}

The meaning of 'extern "C" __declspec(dllexport)' is not really needed to use the technique, but has to be included so that the dll successfully shows the function 'add' to the outside world.  The data is passed into the function via an array of doubles, or rather a pointer to a contiguous series of doubles. Note there is no bounds checking at all so care is required!  Your code then does its calculations with the data and stores the output into the array. This means that you will need to organise some doubles to store the results of your calculations.

From the R point of view this is how you call it:

dyn.load("C:/Users/twright/Documents/Visual Studio 2008/Projects/RtoCPP/Debug/RtoCPP.dll")  

x = .C("add", c(10,20,0))[[1]]

The first line 'dyn.load' loads the dll into R. Note that the address I have used is the location of the dll in the Debug folder of the project file (called RtoCPP). This means I can play with the C++ code and refine it, rebuild and then run it directly from R until it does what I want it to do. Another little trap is to use a / in the path name. I copy the address from a Windows Explorer box and then have to change the direction of the path separator from\ to /.

The .C function then looks up the 'add' function from the functions exported by the dll and then passes the vector of numerics as a parameter. These will be received by the dll as doubles.

The .C function will return a list with [[1]] being the same as the data passed to the function (but altered by the function). Hence my answer would be x[2].

Here is another example:

Lets imagine I want the mean of a vector of numbers v.  From R:

dyn.load("C:/Users/twright/Documents/Visual Studio 2008/Projects/RtoCPP/Debug/RtoCPP.dll")

result = .C("mean", c(0, length(v), v))[[1]]

mean.result = result[1]

Notice that I have added 2 extra numerics before the vector v. The first will be space for the answer and the other one is the length of the vector (since the C++ just receives the address of the start of the sequence of doubles). The variable 'result' is a vector which is the 'post-processed' version of the input to the function. Hence it will have the data and the length in the same location but will have the answer in the 1st slot. Hence 'mean.result' takes the first entry of result.

Now for the C++, which is located as another function inside the RtoCpp dll:

extern "C" __declspec(dllexport) void mean(double* data){

int num = (int)data[1];

data[0] = 0.0;

for (int f=0; f<num; f++) data[0] += data[2+f]

data[0] /= num

}

Of course this process is restricted to sending vectors of real numbers to C++, having them processed and returned, however for a quick 20 min of work I think that it is quite profitable!

Permalink Add your comment
Share post

This blog might contain posts that are only visible to logged-in users, or where only logged-in users can comment. If you have an account on the system, please log in for full access.

Total visits to this blog: 15802