14

我想将可变数量的参数从函数传递给 C/C++,但希望不计算参数,同时不想在 R 中进行任何计算(除了调用 C/C++函数),即我不想调用substitute我的 R 函数。我认为我可以使用的一个选项是.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.

4

1 回答 1

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;
}
于 2013-10-31T16:16:48.953 回答