The problem with your implementation is what happens if R throws an error. The R longjmp will cause any C++ objects on the stack to leak, their destructors not to run, and you'll essentially be in a bad place if you evaluate any R code that might return an error. (For example, suppose you had a file handle open, and then evaluated your R function using 'eval', but an R error was produced. That file handle would 'leak' and you wouldn't be able to recover it)
You can instead use the `Rf_tryEval` or `Rf_tryEvalSilent` routines, but those don't respect active handlers (e.g. warning, message handlers) and so aren't sufficient for general use. Rcpp basically handles this by enclosing any expression to be evaluated in an R 'tryCatch' call, with error + interrupt handlers attached. This is, of course, slower since a lot more R code is being evaluated, but right now it's the only way to safely execute an R function in a C++ context while respecting all other active handlers. In short, the Rcpp::Function implementation is designed to be as safe + correct as possible, with the downside being that it's slower. However, we generally advise that you shouldn't call back to R too frequently from a C++ context, so that overhead should in most cases be not too bad. Best, Kevin On Wed, Aug 3, 2016 at 10:50 AM, George Vega Yon <g.vega...@gmail.com> wrote: > Hey there, > > Looking at some old R code that I have I found this C++ function that allows > evaluating R-written functions within C++ using Rcpp. While this is no news, > the neat thing of it is that it seems to be faster than Rcpp::Function. > Using microbenchmark I compared using Rcpp::function vs my implementation vs > calling the function from R itself and this is what I got > > Unit: relative > expr min lq mean median uq max neval > cppFuncall(x, fun) 1.3 1.3 1.39 1.3 1.4 83 10000 > RcppFuncall(x, fun) 7.2 7.1 7.13 6.9 6.8 89 10000 > fun(x) 1.0 1.0 1.00 1.0 1.0 1 10000 > > So, on average, while Rcpp::Function took ~7 times the R call took, my > implementation took ~1.3 times. To be sure I was not breaking anything I ran > the example using valgrind and there is no memory leak. The source code for > the test follows: > > -------- example_calling_r_functions.cpp ---- > > #include <Rinternals.h> > #include <Rcpp.h> > > // [[Rcpp::export]] > SEXP cppFuncall(SEXP par, SEXP fn) > { > SEXP R_fcall, ans; > > if(!isFunction(fn)) error("'fn' must be a function"); > R_fcall = PROTECT(lang2(fn, R_NilValue)); > > SETCADR(R_fcall, par); > ans=eval(R_fcall, R_GlobalEnv); > UNPROTECT(1); > return ans; > } > > using namespace Rcpp; > > // [[Rcpp::export]] > SEXP RcppFuncall(NumericVector par, Function fn) > { > return fn(par); > } > > > > /*** R > # R function to be called > fun <- function(x) { > -cos(x[1])*cos(x[2])*exp(-((x[1] - pi)^2 + (x[2] - pi)^2)) > } > > # Input data > set.seed(3331) > x <- runif(1e3) > > # Benchmarking > library(microbenchmark) > microbenchmark( > cppFuncall(x, fun), RcppFuncall(x,fun), fun(x), times=1e4, > unit="relative", control = list(warmup=100) > ) > */ > > -------- example_calling_r_functions.cpp ---- > > I've asked around about how to make things faster for function calls in Rcpp > but, from what I've been told it is difficult since the implementation of > Rcpp::Function actually has to go back to R to work (or something like that > :P). Now, this implementation, -cppFuncall-, has no problem when it comes to > passing wrong arguments, e.g. if you pass a character vector to it R will > complain but there won't be any system crash. One big difference is that > here I'm relying on passing all the function's arguments in a single object > while Rcpp::Function does not. Either way, if this is OK this could be a > nice extra feature for Rcpp, I'm thinking of optimization routines (or other > kinds of algorithms) that rely on calling R functions multiple times. > > The thing is that I'm still learning C++ and I'm not Rinternals expert at > all! So I would love to get some feedback from you guys. Does this function, > -cppFuncall-, looks OK? in other words, am I doing/getting something wrong > here? > > Thanks, > > George G. Vega Yon > +1 (626) 381 8171 > http://www.its.caltech.edu/~gvegayon/ > > _______________________________________________ > Rcpp-devel mailing list > Rcpp-devel@lists.r-forge.r-project.org > https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel _______________________________________________ Rcpp-devel mailing list Rcpp-devel@lists.r-forge.r-project.org https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel