可以使用列表对象调用R中的stop
函数,以便发出特定类型的异常信号。例如,要发出foo
异常信号,我们可以这样做:
foo <- list (
message = "my foo error"
)
class(foo) <- c("foo", "condition")
tryCatch (
stop(foo),
foo = function(e){"never mind foo."}
)
C代码是否有用于执行此操作的接口(表示自定义异常)? Rf_error
仅允许引发一般错误,但不允许指定异常类。
答案 0 :(得分:2)
如何在C ++中执行此操作的标准示例是in this Rcpp Gallery post。
只用第一部分进行一次小编辑:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double takeLog(double val) {
try {
if (val <= 0.0) { // log() not defined here
throw std::range_error("Inadmissible value");
}
return log(val);
} catch(std::exception &ex) {
forward_exception_to_r(ex);
} catch(...) {
stop("c++ exception (unknown reason)");
}
return NA_REAL; // not reached
}
按预期工作:
R> sourceCpp("/tmp/ex.cpp")
R> takeLog(-1)
Error: Inadmissible value
R>
该帖子的其余部分有一些细节。
答案 1 :(得分:2)
基于上面的建议,我写了这个功能,它可以满足我的需要:
void signal_exception(const char* message, const char* condition){
//the condition object
SEXP vec = PROTECT(allocVector(VECSXP, 1));
SET_VECTOR_ELT(vec, 0, mkString(message));
setAttrib(vec, R_NamesSymbol, mkString("message"));
//the class vector
SEXP cls = PROTECT(allocVector(STRSXP, 3));
SET_STRING_ELT(cls, 0, mkChar(condition));
SET_STRING_ELT(cls, 1, mkChar("error"));
SET_STRING_ELT(cls, 2, mkChar("condition"));
setAttrib(vec, R_ClassSymbol, cls);
//signal the condition by calling base::stop
SEXP stop_sym = PROTECT(Rf_install("stop"));
SEXP call = PROTECT(Rf_lang2(stop_sym, vec));
UNPROTECT(4);
Rf_eval(call, R_GlobalEnv);
}
它基本上使用第二个参数推广Rf_error
,您可以使用它来指定错误的类。
我不认为从C调用base::stop
是非常优雅的,只是让它回调.Internal(.signalCondition())
但我看起来目前没有用于直接通知来自条件的API C.