In an introductory post on R APIs to C code, Calling C Code ‘Hello World!’, we explored the .C() function with some ‘Hello World!’ baby steps. In this post we will make a leap forward by implementing the same functionality using the .Call() function.

Is .Call() better than .C()?

A heated but friendly conversation took place on the r-devel email forum this past March about R’s copying of arguments and the merits of .C() and .Call(). It is perhaps best to just include a highlight from this exchange. Here is Simon Urbanek responding to Hervé Pagès:

> My understanding is that most packages use the .C interface > because it's simpler to deal with and because they don't need > to pass complicated objects at the C level, just atomic vectors. > My guess is that it's probably rarely the case that the cost > of copying the arguments passed to .C is significant, but, > if that was the case, then they could always call .C() with > DUP=FALSE. However, using DUP=FALSE is dangerous (see Warning > section in the man page). > > No need to switch to .Call > I strongly disagree. I'm appalled to see that sentence here. The overhead is significant for any large vector and it is in particular unnecessary since in .C you have to allocate *and copy* space even for results (twice!). Also it is very error-prone, because you have no information about the length of vectors so it's easy to run out of bounds and there is no way to check. IMHO .C should not be used for any code written in this century (the only exception may be if you are passing no data, e.g. if all you do is to pass a flag and expect no result, you can get away with it even if it is more dangerous). It is a legacy interface that dates way back and is essentially just re-named .Fortran interface. Again, I would strongly recommend the use of .Call in any recent code because it is safer and more efficient (if you don't care about either attribute, well, feel free ;)).

The important differences between the two R interfaces to C code are summarized here:

.C()

allows you to write simple C code that knows nothing about R

only simple data types can be passed

all argument type conversion and checking must be done in R

all memory allocation must be done in R

all arguments are copied locally before being passed to the C function (memory bloat)

.Call()

allows you to write simple R code

allows for complex data types

allows for a C function return value

allows C function to allocate memory

does not require wasteful argument copying

requires much more knowledge of R internals

more knowledge of R internals is the recommended, modern approach for serious C programmers

To allow readers to compare for themselves how difficult or easy it is to switch from .C() to .Call() we will re-implement our three “Hello World!” examples using the .Call() interface.

Getting used to SEXP

The first thing you have to embrace when using the .Call() interface is the new way of dealing with R objects inside your C code. Excellent introductory information and example code is available here:

In preparation for working with .Call() you will want to familiarize yourself with the location of R’s include files. The following Unix shell commands show how to find where R is installed and then look at the contents of the include directory:

$ R RHOME /usr/lib/R $ ls -1 `R RHOME`/include Rconfig.h Rdefines.h Rembedded.h R_ext R.h Rinterface.h Rinternals.h Rmath.h Rversion.h S.h

Here’s what they contain:

Rconfig.h various configuration flags Rdefines.h lots of macros of interest, includes Rinternals.h Rembedded.h function declarations for embedding R in C programs R_ext directory of include files for specific data types, etc. R.h includes all the files found in R_ext Rinterface.h provides hooks for external GUIs Rinternals.h core R data structures Rmath.h math constants and function declarations Rversion.h version string components S.h macros for S/R compatibility

With the .Call() interface, the C function needs to be of type SEXP — a pointer to a SEXPREC or Simple EXPression RECord. We’ll get the definition of SEXP and everything else we need by including both R.h and Rdefines.h in our code. So here is the C code for our first, brain dead C function — helloA1.c:

#include #include #include SEXP helloA1() { printf("Hello World!

"); return(R_NilValue); }

Note that, even though we are returning R_NilValue (aka NULL), the function is declared to be of type SEXP. The function will always be of type SEXP, as will any arguments. It will be up to the C code to convert other data types into and out of SEXP. As in the previous post, you should compile this code with R CMD SHLIB helloA1.c. Here is the very simple R function we need to add to wrappers.R: