This is an experiment in using RCIndex to collect information about a C routine
called from R with .Call().
The C code is in the file return42.c, which defines one routine,
return42(). The return42() routine uses the R API to return the integer 42
as an R INTSXP. The code is:
#include <R.h>
#include <Rinternals.h>
SEXP return42() {
return ScalarInteger(42);
}
The primary complication in this code is that ScalarInteger is a macro that
calls the routine Rf_ScalarInteger(). The Rf_ScalarInteger() routine is
defined as the inline routine ScalarInteger() in Rinlinedfuns.h. The code
for this is:
INLINE_FUN SEXP ScalarInteger(int x)
{
SEXP ans = allocVector(INTSXP, 1);
SET_SCALAR_IVAL(ans, x);
return ans;
}
As a consequence, we will have to work with multiple translation units even to
get information about the relatively simple return42() routine.
We can use createTU() in RCIndex to create a translation unit for the
return42.c file. We must set the include = parameter so that RCIndex can
find the R header files.
library(RCIndex)
includes = c("../../../r-source/src/include")
tu = createTU("return42.c", includes = includes)
Once we have the translation unit, we can get the list of routines with
getRoutines():
routines = getRoutines(tu)
Now let's examine the body of the return42() routine. We could use the code
in return42() to determine its return type.
ret42 = routines[["return42"]]
We can access the body of the routine with getChildren() (but strangely, not
the children() function). If we were processing the routine
non-interactively, we would use visitCursor() instead. Later, we will discuss
a strategy for using visitCursor() to extract the information we need.
The second child is the body of the function. Its children are the statements in the function; in this example, there is only one, a return statement.
bod = getChildren(ret42)[[2]]
ret = children(bod)[[1]]
Since libclang runs the preprocessor, the ScalarInteger macro is
translated into a call to Rf_ScalarInteger(). this call to
Rf_ScalarInteger() is the only child of the return statement. We can access
this call the same way we have accessed other children so far. The call
contains a reference to the definition of the routine being called. We can get
this with getCursorReferenced().
call = children(ret)[[1]]
fn = getCursorReferenced(call)
This gives us a reference to the declaration of Rf_ScalarInteger(). However,
this seems to be the header declaration and does not give us the definition. So
we need to figure out how to get at the definition.
There is a getCursorDefinition() function in RCIndex, but for fn this
returns CXCursor_FirstInvalid.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.