This document provide brief instruction for calling C from R using Rcpp. This chapter from Advanced R provides a wonderful and comprehensive description of Rcpp. Many materials in this lecture are borrowed from there.

There are two old-fashion R-to-C interfaces: .C and .Call, for those I have some description here, and some comparisons here.


Prerequisite


Other resources :


Inline C code with cppFunction

We demonstrate this using a very simple Hello world example. It just prints out a Hello world message. There’s no input/output.

library(Rcpp)
cppFunction( 'void hello() {
              printf("Hello world"); }' )
hello()

A few notes:


Standalone C code with sourceCpp

In most cases you want to write and save your C/C++ codes in a seperate file. Below is my hello function, which is saved in a seperate file hello.cpp.

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
void hello() {
    printf("Hello world! \n");
}

The function can be compiled and load into R by

sourceCpp("hello.cpp")

Now the function can be accessed in R by hello().

A few notes:


Compile and load standalone Rcpp function

To recompile the C++ code for every new R session is not ideal. To compile it once and use forever, there are two options:


With input and output

Now we will write a slightly more complicated function to compute the sum of a vector. Here is the C code named mySum.cpp. It takes a vector from R, computes and returns the sum.

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]                                                                                                   
double mySum(NumericVector x) {
    int i;
    double result=0.0;

    for(i=0; i<x.size(); i++)
        result = result + x[i];
    return(result);
}

Now we can compile and run it in R

sourceCpp("mySum.cpp")
mySum(1:10)

A few notes:


Working with Matrix in C++

The function below (myRowSum.cpp) computes the row-wise sums of a matrix.

#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]                                                                                                   
NumericVector myRowSum( NumericMatrix x ) {
    int nrow = x.nrow(), ncol = x.ncol();
    int i, j;
    double tmp;
    NumericVector result(nrow);

    for(i=0; i<nrow; i++) {
        tmp = 0.0;
        for(j=0; j<ncol; j++)
            tmp = tmp + x(i,j);
        result[i] = tmp;
    }
    return(result);
}

Now we can compile run the code in R

sourceCpp("myRowSum.cpp")
X = matrix(1:6, ncol=2)
myRowSum(X)

A few notes:


Rcpp data types

Variables passed from R to C++ need to be declared with correct data types. Basic data types in C++ are:

For more complex data types and classes (list, data frame, function, etc.) please refer to the Rcpp manual.


C++ code with R package

Now I want to create a package pkgwithRcpp with some C++ codes. Assume I have the cpp file (myRowSum.cpp) in current directory, I can do the following:

  1. Run

    Rcpp.package.skeleton("pkgwithRcpp", cpp_files="myRowSum.cpp", 
                          example_code=FALSE, attributes=FALSE)

    This creates the package skeleton. Note that

    • Rcpp.package.skeleton is a function in Rcpp providing similar functionality of the standard package.skeleton function. But it addes additional lines in DESCRIPTION and NAMESPACE files to ensure the C++ codes can be accessed.
    • After this step, a new directory pkgwithRcpp will appear in current directory with necessary files.
    • Under pkgwithRcpp, there is a src subdirectory containing the C++ code.
    • Under pkgwithRcpp, the R subdirectory is empty.
  2. Run Rcpp::compileAttributes("pkgwithRcpp"). This step will scan the package and generate some necessary files. After this step, a new file RcppExports.R will appear in the R subdirectory, which defines the R interface function for the C function.

  3. Now the package can be built and installed using typical procedure.

A few notes:

For more details, view vignette("Rcpp-package").


Debug standalone C code

Here I will introduce how to debug a standalone C code. Debugging C code within an R package is slightly different, which will be introduced later.

Debugging function is platform-dependent.

As an example below, I debug myRowSum function. The typical steps are:

  1. Run R within a GNU debugger.

    • On linux, run R -d gdb.
    • On newer versions of Mac OSX, run R -d lldb.
  2. Once we are in the debugger, start R by doing run. Then we will be in the R console.

  3. Debugging steps.

    • Compile and load in the function sourceCpp("myRowSum.cpp").
    • Press Control-C to switch back to lldb environment.
    • Set a breakpoint, say, at line 11: myRowSum.cpp:11.
    • After setting breakpoint, go back to R by typing continue in lldb. Now we come back to R.
    • Run the following codes.
        X = matrix(1:6, ncol=2)
        myRowSum(X)
    • Once the breakpoint in myRowSum is hit, it will go to lldb environment. We can then do all sorts of debugging, such as run line by line, inspect the value of variables, etc.

For detailed commands for gdb and lldb, see https://lldb.llvm.org/use/map.html.


Debug C code with R package

Debug C/C++ codes with an R package is a little troubler. Here is an excellent description: https://blog.davisvaughan.com/2019/04/05/debug-r-package-with-cpp/.

The first important thing is to make sure the C/C++ codes are compiled with a “debug-able” flag (usually a -g). This can be achieved by modifying the .R/Makevars files (Or you can run usethis::edit_r_makevars() in R) by adding a few lines like

CXXFLAGS = -g -O0
CFLAGS = -g -O0
CPPFLAGS = -g -O0

Make sure you change it back (from -O0 to -O2), or remove this file after debugging. Otherwise all future packages will be compiled with debug flag, which will make them slower.

The general steps of debuggin the C/C++ codes with an R package is:

  1. Start R with with debugger R -d lldb
  2. Run R in lldb
  3. Load in library
  4. Break back to lldb (Control-C), set breakpoint in C code.
  5. Back to R by `continue’, call R function. Once the breakpoint is hit, it will go to lldb.