1

I am trying to call my R function from C++ program.

rtest = function(input ,output) {
  a <- input
  b <- output 
  outpath <- a+b
  print(a+b)
  return(outpath)
}

This is my R function. I need to find a way for calling this function from C with passing arguments. calling a R function from python code with passing arguments. Here i have made similar method for calling R from python. So i need to specify the path to R script and the name of the function, and also able to pass the arguments through python. I am looking for similar way in C. But didn't get results. This may be a simple thing. Any help is appreciated.

9113303
  • 852
  • 1
  • 16
  • 30

1 Answers1

4

This question has multiple interpretations, which is why I did not attempt an answer before. Here Solutions for several possible interpretations:

C++ function defined with Rcpp that is called from R and uses a user defined R function. This follows http://gallery.rcpp.org/articles/r-function-from-c++/:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector callFunction(NumericVector x, NumericVector y, Function f) {
  NumericVector res = f(x, y);
  return res;
}

/*** R
set.seed(42)
x <- rnorm(1e5)
y <- rnorm(1e5)

rtest <- function(x, y) {
  x + y
}

head(callFunction(x, y, rtest))
head(x + y)
*/

The R function rtest is defined in R and passed to the C++ function callFunction together with it's two arguments. Partial result from Rcpp::sourceCpp():

> head(callFunction(x, y, rtest))
[1]  0.95642325 -0.57197358 -1.45084989 -0.18220091  0.07592864  0.56367202

> head(rtest(x, y))
[1]  0.95642325 -0.57197358 -1.45084989 -0.18220091  0.07592864  0.56367202

Calling the function in R and via C++ gives the same result.

C++ program using RInside which calls an user defined R function on data present in C++. Here we have two possibilities: either transfer the data to R and call the function there or move the function to C++ and call the R function in C++ like above:

#include <RInside.h>

int main(int argc, char *argv[]) {
    // define two vectors in C++
    std::vector<double> x({1.23, 2.34, 3.45});
    std::vector<double> y({2.34, 3.45, 1.23});
    // start R
    RInside R(argc, argv);
    // define a function in R
    R.parseEvalQ("rtest <- function(x, y) {x + y}");
    // transfer the vectors to R
    R["x"] = x;
    R["y"] = y;
    // call the function in R and return the result
    std::vector<double> z = R.parseEval("rtest(x, y)");
    std::cout << z[0] << std::endl;

    // move R function to C++
    Rcpp::Function rtest((SEXP) R.parseEval("rtest"));
    // call the R function from C++
    z = Rcpp::as<std::vector<double> >(rtest(x, y));
    std::cout << z[0] << std::endl;
    exit(0);
}

In order to compile this, I am using the GNUmakefile that comes with the examples in RInside. Result:

$ make -k run
ccache g++ -I/usr/share/R/include -I/usr/local/lib/R/site-library/Rcpp/include -I/usr/local/lib/R/site-library/RInside/include -g -O2 -fdebug-prefix-map=/home/jranke/git/r-backports/stretch/r-base-3.5.0=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -Wno-ignored-attributes -Wall    call_function.cpp  -Wl,--export-dynamic -fopenmp -Wl,-z,relro -L/usr/lib/R/lib -lR -lpcre -llzma -lbz2 -lz -lrt -ldl -lm -licuuc -licui18n  -lblas -llapack  -L/usr/local/lib/R/site-library/RInside/lib -lRInside -Wl,-rpath,/usr/local/lib/R/site-library/RInside/lib -o call_function

Running call_function:
3.57
3.57
Ralf Stubner
  • 26,263
  • 3
  • 40
  • 75
  • I was looking for this type of method. But still facing some import error even after specifying the location of header. Thanks – 9113303 Jul 02 '18 at 11:36
  • 1
    @9113303 Are you using the same command line as I or are you using the referenced Makefile? – Ralf Stubner Jul 02 '18 at 11:41
  • Thanks. This gnu makefile works for me. But ccache didnt works. But still i have 1 more doubt x+y (1.23+2.34) gives the first value 3.57, what about the other one, – 9113303 Jul 02 '18 at 12:12
  • 1
    It is not surprising that the command-line from my system does not work for you. Fortunately these system differences can be abstracted away, e.g. with that Makefile. As for the second `3.57`: The `rtest` function is called twice and the output is therefore printed twice. You can look at previous revisions of this answer were I used different functions. – Ralf Stubner Jul 02 '18 at 12:28
  • Is it possible to pass arguments to the .exe created after `make`, or the data must already be present in c++? – gaut Feb 18 '19 at 20:10
  • 1
    @gpier You will need the variables declared in the C++ code. The actual data might also come from command-line arguments, file input, ... – Ralf Stubner Feb 18 '19 at 20:36
  • @RalfStubner I just posted a new question about this, could you perhaps take a look? https://stackoverflow.com/q/54756011/5224236 – gaut Feb 18 '19 at 22:03