Also note that you definitely don't want to call `Rf_error` from a C++ context in general, as it will bypass any active C++ try-catch blocks, bypass destructors, and so on. You should call `Rcpp::stop` explicitly and use Rcpp attributes to ensure the try-catch block is automagically set up for you.
On Wed, Aug 3, 2016 at 11:28 AM, Kevin Ushey <kevinus...@gmail.com> wrote: > 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