如果输入类型错误,如何制作触发“有用”错误消息的 cpp (Rcpp) 函数?

How to make a cpp (Rcpp) function that triggers "useful" error messages if the input types are wrong?

提问人:Kelvin Grove 提问时间:10/31/2023 更新时间:10/31/2023 访问量:75

问:

考虑这个 cpp 函数

// [[Rcpp::export]]
int timesTwo(int x) {
  return x * 2;
}

如果我在此函数中输入错误类型的对象(例如“字符”),显然它将不起作用并显示此错误消息Error: Not compatible with requested type: [type=character; target=integer].

但是,例如,我想让它提供更多信息

Error in timesTwo(int x)
Error: Not compatible with requested type: [type=character; target=integer].

Error in the parameter x of timesTwo(int x)
Error: Not compatible with requested type: [type=character; target=integer].

我想知道如何在 cpp 中做到这一点?

C++ R 错误处理 RCPP

评论

1赞 PGSA 10/31/2023
gallery.rcpp.org/articles/intro-to-exceptions 给出了一些想法(虽然不完美)
4赞 Allan Cameron 10/31/2023
为什么不编写一个 R 包装函数来执行类型检查、发出有用的错误,并且仅在满足条件时调度 cpp 函数?或者,编写 cpp 函数以接受任何 SEXP 而不是 int,并在其中执行类型检查。
0赞 Botje 10/31/2023
该错误消息似乎是由 rcpp 本身生成的 您可以尝试自己在 Rcpp 中改进它吗?

答:

3赞 Allan Cameron 10/31/2023 #1

有两种明显的方法可以处理这个问题。第一种是通过 R 中的包装器调用 cpp 函数,该包装器会提前执行类型检查。例如:

Rcpp::cppFunction('
  int times_two_cpp(int x) {
    return x * 2;
  }')

timesTwo <- function(x) {
  if(!is.integer(x)) stop("'x' should be an integer, not ", typeof(x))
  times_two_cpp(x)
}

测试,我们有:

timesTwo(5L)
#> [1] 10

timesTwo('hello')
#> Error in timesTwo("hello") : 'x' should be an integer, not character

第二个选项是允许 C++ 函数接受任何 R 对象,并在内部进行类型检查。这需要对 R 内部结构有一定的了解

Rcpp::cppFunction('
  Rcpp::IntegerVector timestwo(SEXP x) {
    if(TYPEOF(x) != INTSXP) {
     Rcpp::stop("in the parameter x of timesTwo - x is not an integer");
    }
    Rcpp::IntegerVector result(x);
    return result * 2;
   }
')

导致

timestwo(5L)
#> [1] 10

timestwo('hello')
#> Error: in the parameter x of timesTwo - x is not an integer