通过未计算前pressions到C / C ++ [英] passing unevaluated expressions to C/C++

查看:94
本文介绍了通过未计算前pressions到C / C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从一个函数,C / C ++传递可变数量的参数,但想离开的参数未评估,并在同一时间不想从调用做R中的任何计算(除了C / C ++函数),即我不想叫替代在我的R函数。为此,我认为我可以用一个选项是 .External 和做水木清华这样的:

I'd like to pass a variable number of arguments from a function to C/C++, but would like to leave the arguments unevaluated and at the same time don't want to do any computations in R (aside from calling the C/C++ function), i.e. I don't want to call substitute in my R function. One option for this that I thought I could use is .External and doing smth like this:

R_fn = function(...) .External("cpp_fn", ...)

...
# and in C code:
SEXP cpp_fn (SEXP arglist) {
}

.External ... 评估参数,所以如果我尝试像

However .External is evaluating arguments in ..., so if I try something like

rm(x, y) # just making sure these don't exist

R_fn(x*y)

我得到一个错误,因为R的尝试评估 X * Y 的发送到功能。

要相比之下,在R中的以下工作:

To contrast, the following works in R:

f = function(...) g(...)
g = function(x, ...) print(substitute(x))

f(x*y*z)
# x * y * z

我有什么其他选择?显然,这是可以做到的R本身做它的一些功能,例如替代本身,但我不知道该怎么做。我加了 RCPP 标记,因为我的这个最终用途将是在 RCPP

What other options do I have? Clearly it's possible to do as R itself does it for a number of functions, e.g. substitute itself, but I don't understand how to do it. I added the rcpp tag because my eventual usage of this is going to be in Rcpp.

推荐答案

一种可能性是做什么 match.call 做(感谢里卡多沙巴达指着我在方向)。这需要复制粘贴从研发源头code一些定义,我不会在这里做的,但基本的想法是从 R_GlobalContext 获取调用函数,然后从那里提取函数的参数。画稿如下:

One possibility is to do what match.call does (thanks to Ricardo Saporta for pointing me in that direction). This requires copy-pasting a few definitions from R source code that I won't do here, but the basic idea is to get the calling function from R_GlobalContext and then extract the function arguments from there. The rough sketch is as follows:

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;
}

这篇关于通过未计算前pressions到C / C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆