因此,我使用一种有点笨拙的解决方法解决了这个问题,但经过认真考虑后,这是我尝试实施的三种方法中最不笨拙的一种。
我最终采用的方法是检查 R 端函数的methods::formalArgs
arity ,将 (function, arity) 对包装在一个列表中,并将其传递给 Rcpp 函数,如下所示:
double loglikelihood(Rcpp::List data, Rcpp::List params,
SEXP i, Rcpp::RObject custom_function) {
Rcpp::List l = Rcpp::as<Rcpp::List>(custom_function);
Rcpp::Function f = Rcpp::as<Rcpp::Function>(l[0]);
int arity = l[1];
double res = 0.0;
if (arity == 3) {
res = Rcpp::as<double>(f(data, param, i));
} else if (arity == 2) {
res = Rcpp::as<double>(f(data, param));
}
return res;
}
正如我所提到的,这有点笨拙,它改变了函数的签名,这并不理想。另一种方法是使用宽恕而不是许可方法并在 try-catch 块中执行控制流,如下所示:
double loglikelihood(Rcpp::List data, Rcpp::List params,
SEXP i, Rcpp::RObject custom_function) {
Rcpp::Function f = Rcpp::as<Rcpp::Function>(custom_function);
double res = 0.0;
try {
res = Rcpp::as<double>(f(data, param, i));
} catch (const std::exception &e) {
res = Rcpp::as<double>(f(data, param));
}
return res;
}
这种方法不那么笨重,但它的问题是它还捕获了可能在其中出现的其他异常f
并将它们静音,因此它们不会传递给用户。有可能在 Rcpp 中定义了更细粒度的异常,它们能够捕获传递太多参数的特定错误,但如果是这样我还没有找到。
最后,我们可以在我们需要使用它之前传递并查询它,但我认为这种方法是三种方法中最笨拙的,因为它需要我们传递methods::formalArgs
很多。loglikelihood
formalArgs