Thursday, September 27, 2007

Using C functions in R

Method:
convert .c file to shared library .so via link ready object file .o, then use dyn.load() in R to call the shared library, and use .C() to convert it to R function.

Example 1, conv
Feature: simple c example without external library.

1.1 C code:
/* conv.c */
void convolve(double *a, int *na,
double *b, int *nb, double *ab){
int i, j, nab=*na + *nb -1;

for (i=0; i<nab; i++)
ab[i] = 0.0;

for (i=0; i<*na; i++)
for (j=0; j<*nb; j++)
ab[i+j] = ab[i+j] + a[i]*b[j];

1.2 Terminal Process:
gcc -c conv.c
R CMD SHLIB conv.o

R CMD SHLIB conv.c

1.3 R code:
# conv.r
dyn.load("conv.so");

conv <- function(a, b){ .C("convolve", as.double(a), as.integer(length(a)), as.double(b), as.integer(length(b)), ab = double(length(a)+length(b)-1))$ab } x <- 1:3 y <- 1:5 z <- conv(x,y)



Example 2, Exp1
Feature: c example with gsl library.

2.1 C code:
/* exp1.c */
#include
void myexp(double *x, int *nx, double *y){
int i;
for (i=0; i<*nx; i++){ y[i] = gsl_sf_expint_E1(x[i]); } }


2.2 Terminal Process:

gcc -c exp1.c
gcc -shared -o exp1.so exp1.o -lgsl -lblas -lm

R CMD SHLIB exp1.o /usr/lib/libgsl.a

2.3 R code:

# exp1.r
dyn.load("exp1.so");

myexp <- function(x){
.C("myexp", as.double(x), as.integer(length(x)),
y = double(length(x)))$y;
}
myexp(1:4);


Example 3, Exp1 in C++
Feature: C++ example with gsl library.
How: just wrap all functions in extern “C”{}.

3.1 C code:
/* exp1.cpp */
#include <gsl/gsl_sf_expint.h>
extern “C”{
void myexp(double *x, int *nx, double *y){
int i;
for (i=0; i<*nx; i++){ y[i] = gsl_sf_expint_E1(x[i]); } } }


3.2 Terminal Process:
g++ -c exp1.cpp
g++ -shared -o exp1.so exp1.o -lgsl -lblas -lm

R CMD SHLIB exp1.o /usr/lib/libgsl.a

3.3 R code:
# exp1.r
dyn.load("exp1.so");
myexp <- function(x){ .C("myexp", as.double(x), as.integer(length(x)), y = double(length(x)))$y; } myexp(1:4);

No comments: