我想将一个函数的可变数量的参数传递给C / C ++,但是希望保持参数不被评估,同时又不想在R中进行任何计算(除了调用C / C ++函数),即我不想在我的R函数中调用substitute
。我认为我可以使用的一个选项是.External
并像这样做:
R_fn = function(...) .External("cpp_fn", ...)
...
# and in C code:
SEXP cpp_fn (SEXP arglist) {
}
但是.External
正在评估...
中的参数,所以如果我尝试类似
rm(x, y) # just making sure these don't exist
R_fn(x*y)
我收到错误,因为R在将其发送到函数之前尝试评估x*y
。
相比之下,以下内容适用于R:
f = function(...) g(...)
g = function(x, ...) print(substitute(x))
f(x*y*z)
# x * y * z
我还有其他选择吗?显然,它可以做,因为R本身就可以用于许多功能,例如: substitute
本身,但我不明白该怎么做。我添加了rcpp
代码,因为我最终会在Rcpp
使用此代码。
答案 0 :(得分:5)
一种可能性是做match.call
所做的事(感谢Ricardo Saporta将我指向那个方向)。这需要从R源代码中复制粘贴一些我不会在这里做的定义,但基本的想法是从R_GlobalContext
获取调用函数,然后从那里提取函数参数。草图如下:
R_fn = function(...) .Call("cpp_fn")
// and in C++ code
Language cpp_fn() {
SEXP sysp = ((RCNTXT*)R_GlobalContext)->sysparent;
RCNTXT *cptr = (RCNTXT*)R_GlobalContext;
while (cptr != NULL) {
if (cptr->callflag & CTXT_FUNCTION && cptr->cloenv == sysp)
break;
cptr = cptr->nextcontext;
}
cptr = cptr->nextcontext; // because this is called from .Call and not from R_fn
// and now cptr->promargs has the unevaluated arguments to do as one pleases
// e.g.
Language firstArg(R_PromiseExpr(CAR(cptr->promargs)));
return firstArg;
}