Call C from R and R from C

[This article was first published on Quantitative Ecology, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Several years ago, while a research associate at the University of Chicago, I had the privilege of sitting in on a course taught by Peter Rossi: Bayesian Applications in Marketing and MicroEconometrics. This course — one I recommend to anyone at U Chicago who is interested in statistics — was an incredibly clear treatment of Bayesian statistics, but the aspect I appreciated most was Peter’s careful demonstration of Bayesian theory and methods using R.

One feature of R that I had not made use of up until that point was the ability to call compiled C and Fortran functions from within R (this makes loop-heavy Metropolis-Hastings samplers much, much faster). It turns out that you can also include the R libraries in C source code so that R functions (e.g., random number generators) can be easily accessed. The R-Cran website has an excellent tutorial on how to develop R extensions (here), but I wanted to share an example Peter used in class because it is extremely brief, and for 95% of what I do, this is all I need.

As Peter writes, this is an incredibly inefficient way of simulating from the chisquare distribution, but it demonstrates the point. His more extensive writeup is located here.

Save the following as testfun.c:
#include <R.h>
#include <Rmath.h>
#include <math.h>
/* Function written by Peter Rossi from the University of Chicago GSB                */
/* */

/* include standard C math library and R internal function declarations     */
void mychisq(double *vec, double *chisq, int *nu)
                                       /* void means return nothing */
  int i,iter;                          /* declare local vars */
                                       /* all statements end in;     */
  GetRNGstate();                       /* set random number seed     */
  for (i=0 ; i < *nu; ++i)
                                       /* loop over elements of vec */
                                       /*nu "dereferences" the pointer */
  {                                    /* vectors start at 0 location!*/
        vec[i] = rnorm(0.0,1.0);       /*use R function to draw normals */
        Rprintf("%ith normal draw= %lf \n",(i+1),vec[i]);
                                       /* print out results for "debugging"      */
  while(iter < *nu)                    /* "while" version of a loop */
        if( iter == iter)
               {*chisq=*chisq + vec[iter]*vec[iter];}
                                       /* redundant if stmnt */
        iter=iter+1;                   /* note: can't use ** */
        /* if you want to be "cool" use iter += 1 */
  PutRNGstate();                       /* write back ran number seed */

To call this function in R, you first need to compile it. To do this you need all the standard compilers and libraries for your operating system. For Debian or Ubuntu, this should do it (if I missed a package, let me know in the comments):
$ sudo aptitude update
$ sudo aptitude install build-essential r-base-dev

Now, you should be able to compile the function:
$ R CMD SHLIB testfun.c

If all goes well, you should see the files testfun.o and in the directory. To test the function we will source the following R script into R:
##This function is just a wrapper for .C
vector=double(nu); chisq=1

##Load the compiled code (you may need to include 
## the explicit file path if it is not local
## NOTE: for Windows machines, you will want to load testfun.dll" 

##If you re-compile testfun.c, you must unload it
## and then re-load it:
## dyn.unload("")
## dyn.load("")

And get the following output:
> dyn.load("")
> result<-call_mychisq(10) 1th normal draw= -1.031170  2th normal draw= -1.214103  3th normal draw= 0.002335  4th normal draw= 0.296146  5th normal draw= -0.908862  6th normal draw= -1.567820  7th normal draw= -0.079227  8th normal draw= -1.404414  9th normal draw= 0.616567  10th normal draw= -0.007855   > result
[1] 8.268028

To leave a comment for the author, please follow the link and comment on their blog: Quantitative Ecology. offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)