简体   繁体   中英

How to call C function from R?

How can you use some function written in C from R level using R data. eg. to use function like:

double* addOneToVector(int n, const double* vector) {
    double* ans = malloc(sizeof(double)*n);
    for (int i = 0; i < n; ++i)
        ans[i] = vector[i] + 1
    return ans;
}

in the context:

x = 1:3
x = addOneToVector(x)
x # 2, 3, 4

I've searched stackoverflow first but I noticed there is no answer for that in here.
The general idea is (commands for linux, but same idea under other OS):

  1. Create function that will only take pointers to basic types and do everything by side-effects (returns void). eg:

     void addOneToVector(int* n, double* vector) { for (int i = 0; i < *n; ++i) vector[i] += 1.0; }
  2. Compile file C source as dynamic library, you can use R shortcut to do this:

     $ R CMD SHLIB lib.c
  3. Load dynamic library from R:

     dyn.load("foo.so")
  4. Call C functions using .C R function, IE:

     x = 1:3 ret_val = .C("addOneToVector", n=length(x), vector=as.double(x))

It returns list from which you can get value of inputs after calling functions eg.

ret_val$x # 2, 3, 4

You can now wrap it to be able to use it from R easier.

There is a nice page describing whole process with more details here (also covering Fortran):

http://users.stat.umn.edu/~geyer/rc/

I just did the same thing in a very simple way using the Rcpp package . It allows you to write C++ functions directly in R.

library("Rcpp")
cppFunction("
NumericVector addOneToVector(NumericVector vector) {
  int n = vector.size();

  for (int i = 0; i < n; ++i)
    vector[i] = vector[i] + 1.0;

  return vector;
}")

Find more details here http://adv-r.had.co.nz/Rcpp.html . C++ functions can be done very fast with these instructions.

First off, I wanted to thank both @m0nhawk and @Jan for their immensely useful contributions to this problem.

I tried both methods on my MacBook: first the one showed m0nhawk which requires creating a function in C (without the main method) and then compiling using R CMD SHLIB <prog.c> and then invoking the function from R using the .C command

Here's a small C code I wrote (not a pro in C - just learning in bits and pieces)

Step 1: Write the C Program

#include <stdio.h>
int func_test() {
    
    for(int i = 0; i < 5; i++) {
        printf("The value of i is: %d\n", i);
    }
    return 0;

}

Step 2: Compile the program using

R CMD SHLIB func_test.c

This will produce a func_test.so file

Step 3: Now write the R Code that invokes this C function from within R Studio

dyn.load("/users/my_home_dir/xxx/ccode/ac.so")
.C("func_test")

Step 4: Output:

.C("func_test") The value of i is: 0 The value of i is: 1 The value of i is: 2 The value of i is: 3 The value of i is: 4 list()

Then I tried the direct method suggested by Jan - using the RCpp package

library("Rcpp")
cppFunction("
NumericVector addOneToVector(NumericVector vector) {
  int n = vector.size();

  for (int i = 0; i < n; ++i)
    vector[i] = vector[i] + 1.0;

  return vector;
}")

# Test code to test the function
addOneToVector(c(1,2,3))

Both methods worked superbly. I can now start writing functions in C or C++ and use them in R

Thank you once again!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM