How to generate an R warning safely in Rcpp

守給你的承諾、 提交于 2019-12-20 17:33:13

问题


We know that calling Rf_error() should be avoided in Rcpp as it involves a longjmp over C++ destructors on the stack. This is why we rather throw C++ exceptions in Rcpp code (like throw Rcpp::exception("...") or via the stop("...") function).

However, R warnings may also result in a call to Rf_error() (this behavior depends on the warn option). So, a call to Rf_warning() is also risky.

Rcpp::sourceCpp(code = '

   #include <Rcpp.h>
   using namespace Rcpp;

   class Test {
      public:
         Test() { Rcout << "start\\n"; }
         ~Test() { Rcout << "end\\n"; }
   };

   // [[Rcpp::export]]
   void test() {
      Test t;
      Rf_warning("test");
   }
')

options(warn=10)
test()
## start
## Error in test() : (converted from warning) test

We see that the destructor hasn't been called (there's no "end" message).

How to generate an R warning in a C++-destructor-friendly way?


回答1:


One of the solutions I came up with involves calling the R's warning function from Rcpp:

// [[Rcpp::export]]
void test() {
   Test t;
   Function warning("warning");
   warning("test"); // here R errors are caught and transformed to C++ exceptions
}

which gives the correct behavior if warn>2:

start
end
Error in eval(expr, envir, enclos) : (converted from warning) test

I wonder if anybody has a better idea for that.




回答2:


I would recommend using stop() (which is a wrapper around try/catch) instead:

With your code slightly modified:

#include <Rcpp.h>
using namespace Rcpp;

class Test {
public:
    Test() { Rcout << "start\n"; }
    ~Test() { Rcout << "end\n"; }
};

// [[Rcpp::export]]
void test() {
    Test t;
    Rf_warning("test");
}

// [[Rcpp::export]]
void test2() {
    Test t;
    stop("test2");
}

/*** R
options(warn=10)
#test()
test2()
*/

I get the desired behaviour:

R> sourceCpp("/tmp/throw.cpp")

R> options(warn=10)

R> #test()
R> test2()
start
end
Error in eval(expr, envir, enclos) (from srcConn#3) : test2
R> 

The longjmp issue is known, but you do not win by avoiding the mechanisms we have to unwind objects.



来源:https://stackoverflow.com/questions/24557711/how-to-generate-an-r-warning-safely-in-rcpp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!