我们知道在Rcpp中应该避免调用Rf_error(),因为它涉及堆栈上的C++析构函数之上的长C++。这就是为什么我们宁愿在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我们看到未调用析构函数(没有“结束”消息)。
如何以C++-析构函数友好的方式生成R警告?
发布于 2014-07-03 15:30:26
我想出的解决方案之一是从Rcpp调用R的warning函数:
// [[Rcpp::export]]
void test() {
Test t;
Function warning("warning");
warning("test"); // here R errors are caught and transformed to C++ exceptions
}它提供了正确的行为,如果warn>2
start
end
Error in eval(expr, envir, enclos) : (converted from warning) test我想知道是否有人对此有更好的想法。
发布于 2014-07-03 15:32:51
我建议使用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()
*/我得到了想要的行为:
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> longjmp问题是众所周知的,但您不能通过避免我们必须解除对象的机制而获胜。
https://stackoverflow.com/questions/24557711
复制相似问题