gag*_*ews 18 warnings r longjmp rcpp
我们知道Rf_error()
在Rcpp中应该避免调用,因为它涉及堆栈上的C++析构函数的longjmp.这就是为什么我们宁愿在Rcpp代码中抛出C++异常(喜欢throw Rcpp::exception("...")
或通过stop("...")
函数).
但是,R警告也可能导致调用Rf_error()
(此行为取决于warn
选项).所以,打电话Rf_warning()
也是有风险的.
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
Run Code Online (Sandbox Code Playgroud)
我们看到析构函数没有被调用(没有"结束"消息).
如何用C++生成R警告 - 对析构函数友好的方式?
gag*_*ews 12
我提出的解决方案之一涉及warning
从Rcpp 调用R的函数:
// [[Rcpp::export]]
void test() {
Test t;
Function warning("warning");
warning("test"); // here R errors are caught and transformed to C++ exceptions
}
Run Code Online (Sandbox Code Playgroud)
在以下情况下给出正确的行为warn>2
:
start
end
Error in eval(expr, envir, enclos) : (converted from warning) test
Run Code Online (Sandbox Code Playgroud)
我想知道是否有人对此有更好的想法.
我建议使用stop()
(这是一个包装try/catch
):
稍微修改您的代码:
#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()
*/
Run Code Online (Sandbox Code Playgroud)
我得到了理想的行为:
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>
Run Code Online (Sandbox Code Playgroud)
该longjmp
问题是已知的,但你不回避,我们必须放松对象的机制获胜.