Akshit
Akshit

Reputation: 434

How to correctly catch the Rcpp exceptions?

I have created a function shown below:

#include <Rcpp.h>


//[[Rcpp::export]]
 void fun(SEXP num = R_NilValue){
        if(!Rf_isNull(num)){
            try{
                  int NUM = Rcpp::as<int>(num);
            }catch(...){
                 Rcpp::stop("Exception occured!");
            }
        }
    }

This function exported as a part of an R package and is included in the Makevars. Now, if I pass in a string value as an argument to this function (fun("a")), I am not able to catch the exception and the R session is aborting and crashing. Is there any way to catch this exception? The goal that I want to achieve in this case is to make sure that incorrect type arguments aren't passed to the function.

If I use the call shown instead of the previous one, the R session aborts:

// [[Rcpp::export]]
std::string fun(int imax = 214748364) {
     return "okay";
} 

Now, a call of fun('a') causes crashes here too even though I have a type mismatch.

Upvotes: 2

Views: 724

Answers (1)

Dirk is no longer here
Dirk is no longer here

Reputation: 368409

Your example is not complete as you did not tell us how you build and called the function.

"In general" you do not need to anything as R does it for you. Simplest example:

R> cppFunction("int doubleMe(int x) { return x + x; }")
R> doubleMe(21)
[1] 42
R> doubleMe("this won't work")
Error in doubleMe("this won't work") : 
  Not compatible with requested type: [type=character; target=integer].
R> 

If you use cppFunction or sourceCpp() in verbose mode you see the generated code. If you follow that code including the #define used you will see that it already includes a try/catch block for you which is why I said you do not need to do anything.

Now, you of course build functions "by hand" the (very) old way with R CMD COMPILE and friends---my old presentations from 10+ years ago show how if you need a quick read---and insert manual try/catch blocks to try this yourself.

In short, "inner" Rcpp code does throw exceptions which is why "outer" Rcpp code is set up to catch them. It works pretty well, and was refined over many years to address most head scratchers with possible OS-dependencies in the implementation.

Edit: Here is an old StackOverflow answer of mine from 2009 showing how to compile "by hand" in the days before Rcpp Attributes. It includes a try/catch block which we always (manually) included then.

Edit 2: Thanks for editing your question. If you use [[Rcpp::export]] the simplest version is

//[[Rcpp::export]]
void fun(int num) {
    // do nothing
}

showing the desired behaviour:

R> sourceCpp("~/git/stackoverflow/63049304/answer.cpp")
R> fun(2)
R> fun("lalala")
Error in fun("lalala") : 
  Not compatible with requested type: [type=character; target=integer].
R> 

Edit 3 Your example, as posted in your last edit, doesn't even compile. Repaired, it behaves as usual.

R> cppFunction('std::string fun(int imax=1234) { return("okay"); }')
R> fun("a")
Error in fun("a") : 
  Not compatible with requested type: [type=character; target=integer].
R> fun('a')
Error in fun("a") : 
  Not compatible with requested type: [type=character; target=integer].
R> 

Upvotes: 2

Related Questions