Dienstag, 5. Mai 2009

05.05.09: 6 Steps to call a C function in R

  • Wrap for netMotifs
  • Submit Abstract for PhD Retreat
  • Read Architecture paper
  • Özgür's WST data and Uli's RTCA data
After some searching and testing, I have began to know how to call a C function in R. The reason for doing this can be speed (for example, the convolution of two finite sequences, as raised by the Writing R Extensions tutorial, refered as 'WRE tutorial'), or existing codes that have been implemented in C or Fortran (e.g., mfinder software source codes kindly provided by Nadav Kashtan, Uri Alon and their colleagues. One may argue that auto-wrapping tools like SWIG (Simplified Wrapper and Inteface Generator) could do this automatically. However it is worth implementing by hand at least in two scenarios:
  • When one wants to embed a C routine in his/her R function/package for the first time, it is defnitely exciting to know how does it work at all.
  • Some complex data structures are not yet fully supported by SWIG. In these cases it is also necessary to understand how to write a wrapper manually.
To call a C function in R, one has to following following steps:
  1. Write a function in C, for example a toy example of function 'myC'.
    void myC(int* lower, int* upper) {
     int i;
     printf("\t Number \t\t Sqaure Root of the Number\n");
     for(i = *lower; i<= *upper; ++i)     
       printf("\t %d \t\t\t %2.2f \n",i, sqrt((double) i));  
  2. Create shared objects of the function myC with R CMD SHLIB myC.c in command line. If neccessary also provide needed parameters, for example -lm. This step produces a myC.so file, namely the shared object.
  3. Use dyn.load("myC.so") function in a R session to load the shared object.
  4. After loading, the function can be called with .C function, with the function name in string as the first parameter followed by parameters to be passed. Please keep in mind that the type of parameter must be checked (coerced) correct before passing, otherwise one may face unexpected results. use the toy function, a call to the function is demonstrated by:

    res <- .C("myC", lower=as.integer(0), upper=as.integer(8))
  5. Now you should see the output of the function, as follows:
      Number    Sqaure Root of the Number
      0     0.00 
      1     1.00 
      2     1.41 
      3     1.73 
      4     2.00 
      5     2.24 
      6     2.45 
      7     2.65 
      8     2.83 
  6. (Optionally) One could unload the shared library by dyn.unload("myC.so").
Some words off-topic: now I think it is not that difficult, however it took me quite a long time to understand the (sometimes too detailed) descriptions in the R extension tutorial: I am not sure whether others have a similar feeling, I believe the quality of documentation in R needs to be improved, especially in the readability and approachability: two common scenario always trouble me: either there is no easy and understandable answer to a question (like the one I am discussing here), or I do not know there is a function in any package implementing a desired task (so called 're-use of the code', preferred to write the code of his own).

Back to the topic, following the procedures described above, one can relative easily wrap a C (or other languages, like Fortran or C++) function in R. The wrapping is desired since at least it may help the check/coerce of the types.

Next step is to embed one or more C files in a package, which normally requires the use of configure and Makevar files. There is also some words spent on this in the WRE tutorial, but to me they are not structured and I did not 'know-how' even after several times of reading. So next step I will also write a demo to show how to do this.