Reputation: 434
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
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