1 Introduction

2 Call C functions from R

2.1 A toy example

Let’s start with a simple function in C.

void test(int *n) 
{ int i; 
  for(i=0; i<*n; i++){
     Rprintf("Test!\n"); 
  } 
}

Now we show how to call this C function in R.

The C part:

  • Save the function in basics.c

  • change the working directory if needed

    ‘pwd’ to check the current working directory; ‘cd’ to change the directory.

  • Compile the C code in your Terminal window or VSCode (Terminal –> New Terminal) with the command (gcc complier is needed!):

R CMD SHLIB basics.c
  • Obtain the two output files: basics.o and basics.so.

The R part:

  • Load the external C code to R by the ‘dyn.load’ function.
dyn.load(‘‘basics.so’’)
  • To invoke this C code in our R session, we need a wrapper function and using the ‘.C’ function in R.
test <- function(n){
  n <- as.integer(n)
  .C("test", n=n) # the first argument is the C function's name, followed by arguments of the C function.
}
  • .C also returns a list containing the arguments which we passed into the C function.
  • A way to modify it.
test <- function(n){
  n <- as.integer(n)
  sol <- .C("test", n=n)
}

2.2 How much can C speed up the comuputation?

In my prepared ‘basics.c’ files, I inclued some functions for vector-matrix and matrix-matrix mutiplications. Let’s see some examples to get an initial feeling of the power of C.

# Example of matrix multiplication
m <- 2e3
n <- 2e3
p <- 2e3

A <- matrix(rnorm(m*n), nrow = m)
B <- matrix(rnorm(n*p), nrow = n)

# run the C code
t <- proc.time()
b_C <- mmprod_C(A, B)
t_C <- proc.time()-t
t_C[[3]]


# run the R code
t <- proc.time()
b_R <- A%*%B
t_R <- proc.time()-t
t_R[[3]]

# !!! The speedup depends on your computer. 

3 Caveats for R’s C interface

Calling C code in R needs more carefulness than using pure R code. Here are some notes for you.

#include <R.h>
#==== Other commonly needed header files
#include <Rmath.h>
#include <math.h>
#include <stdio.h>
#include <R_ext/BLAS.h>
#include <stdlib.h>

4 Build an R package with C code

Building an R package with C code follows the same routine as building a common R package. Some extra wrok is listed below.

library(devtools)
load_all()
document()
# In the Environment pane of your R studio (typically top right), click 'build'
Check 
Build Source Package
Rnstall and Restart

5 Discussion

Overall, I think R’s C interface is helpful for people doing optimization in Statistics or people who care about the computation of statistical problems. Using C backend code can make your code run even ten times faster than using R code. However, you have to pay for the speedup. It requires your knowledge of C. More importantly, it requires your carefulness for writing both the C and R code. I personally think that R’s C interface is not friendly for debugging. It is not like running a C program, or simply writing and running some R code. I have some experience with debugging when using R’s C interface. Tips that I suggested to pay much attention to have been included into the ‘Caveats for R’s C interface’ section.

References

  1. https://cran.r-project.org/doc/manuals/R-exts.html

  2. https://www.biostat.jhsph.edu/~rpeng/docs/interface.pdf