繁体   English   中英

了解如何在R中处理.Internal C函数

[英]Understanding how .Internal C functions are handled in R

我想知道是否有人可以向我说明R如何从控制台提示符下键入的R命令执行C调用。 我对R对a)函数参数和b)函数调用本身的处理特别感到困惑。

我们举一个例子,在这种情况下是set.seed() 想知道它是如何工作的我在提示符下输入名称,获取源代码( 在这里查看更多内容 ),看看最终有一个.Internal(set.seed(seed, i.knd, normal.kind) ,所以尽职尽责在/src/names.c.Internals部分查找相关的函数名,找到它叫做do_setseed并在RNG.c ,这导致我...

SEXP attribute_hidden do_setseed (SEXP call, SEXP op, SEXP args, SEXP env)
{
    SEXP skind, nkind;
    int seed;

    checkArity(op, args);
    if(!isNull(CAR(args))) {
    seed = asInteger(CAR(args));
    if (seed == NA_INTEGER)
        error(_("supplied seed is not a valid integer"));
    } else seed = TimeToSeed();
    skind = CADR(args);
    nkind = CADDR(args);
    //...
      //DO RNG here 
    //...
    return R_NilValue;
}
  • 什么是CARCADRCADDR 我的研究让我相信它们是一个受Lisp影响的有关列表的构造,但除此之外,我不明白这些函数的作用或为什么需要它们
  • checkArity()什么作用?
  • SEXP args似乎是自解释的,但这是函数调用中传递的参数列表吗?
  • SEXP op代表什么? 我认为这意味着运算符(如二进制函数,如+ ),但那么SEXP call是什么?

是否有人能够流经我打字时发生的事情

set.seed(1)

在R控制台提示符下,直到定义skindnkind的点? 我发现我无法很好地理解这个级别的源代码以及从解释器到C函数的路径。

CARCDR是您访问pairlist对象的方式,如R语言定义的 2.1.11节所述 CAR包含第一个元素, CDR包含其余元素。 编写R扩展的第5.10.2节给出了一个例子:

#include <R.h>
#include <Rinternals.h>

SEXP convolveE(SEXP args)
{
    int i, j, na, nb, nab;
    double *xa, *xb, *xab;
    SEXP a, b, ab;

    a = PROTECT(coerceVector(CADR(args), REALSXP));
    b = PROTECT(coerceVector(CADDR(args), REALSXP));
    ...
}
/* The macros: */
first = CADR(args);
second = CADDR(args);
third = CADDDR(args);
fourth = CAD4R(args);
/* provide convenient ways to access the first four arguments.
 * More generally we can use the CDR and CAR macros as in: */
args = CDR(args); a = CAR(args);
args = CDR(args); b = CAR(args);

还有一个TAG宏来访问给实际参数的名称。

checkArity确保传递给函数的参数数量是正确的。 args是传递给函数的实际参数。 op是偏移指针“用于处理多个R函数的C函数”(引自src/main/names.c ,其中还包含显示每个函数的偏移和arity的表)。

例如, do_colsum处理col/rowSumscol/rowMeans

/* Table of  .Internal(.) and .Primitive(.)  R functions
 * =====     =========        ==========
 * Each entry is a line with
 *
 *  printname  c-entry     offset  eval  arity   pp-kind   precedence  rightassoc
 *  ---------  -------     ------  ----  -----   -------   ----------  ----------
{"colSums",    do_colsum,  0,      11,   4,     {PP_FUNCALL, PREC_FN,  0}},
{"colMeans",   do_colsum,  1,      11,   4,     {PP_FUNCALL, PREC_FN,  0}},
{"rowSums",    do_colsum,  2,      11,   4,     {PP_FUNCALL, PREC_FN,  0}},
{"rowMeans",   do_colsum,  3,      11,   4,     {PP_FUNCALL, PREC_FN,  0}},

请注意,上表中的arity为4,因为(即使rowSums等只有3个参数) do_colsum有4个,您可以从rowSums.Internal调用中rowSums

> rowSums
function (x, na.rm = FALSE, dims = 1L) 
{
    if (is.data.frame(x)) 
        x <- as.matrix(x)
    if (!is.array(x) || length(dn <- dim(x)) < 2L) 
        stop("'x' must be an array of at least two dimensions")
    if (dims < 1L || dims > length(dn) - 1L) 
        stop("invalid 'dims'")
    p <- prod(dn[-(1L:dims)])
    dn <- dn[1L:dims]
    z <- if (is.complex(x)) 
        .Internal(rowSums(Re(x), prod(dn), p, na.rm)) + (0+1i) * 
            .Internal(rowSums(Im(x), prod(dn), p, na.rm))
    else .Internal(rowSums(x, prod(dn), p, na.rm))
    if (length(dn) > 1L) {
        dim(z) <- dn
        dimnames(z) <- dimnames(x)[1L:dims]
    }
    else names(z) <- dimnames(x)[[1L]]
    z
}

基本的C级pairlist提取功能是CARCDR (Pairlists与列表非常相似,但是作为链表实现,并在内部用于参数列表)。 它们具有简单的R等价物: x[[1]]x[-1] R还提供了两者的许多组合:

  • CAAR(x) = CAR(CAR(x))等于x[[1]][[1]]
  • CADR(x) = CAR(CDR(x)) ,相当于x[-1][[1]] ,即x[[2]]
  • CADDR(x) = CAR(CDR(CDR(x))相当于x[-1][-1][[1]] ,即x[[3]]
  • 等等

与访问列表的第n个元素O(1)不同,访问pairlist的第n个元素是O(n)操作。 这就是为什么没有更好的功能来访问pairlist的第n个元素。

内部/原始函数不按名称进行匹配,它们仅使用位置匹配,这就是为什么它们可以使用这个简单的系统来提取参数。

接下来,您需要了解C函数的参数是什么。 我不确定这些文件在哪里记录,所以我可能不完全正确的结构,但我应该是一般的部分:

  • call :完成调用,可能由match.call()捕获

  • op :从R调用的.Internal函数的索引。这是必需的,因为从.Internal函数到C函数有多对一的映射。 (例如, do_summary实现sum,mean,min,max和prod)。 该数字是names.c的第三个条目 - 对于do_setseed ,它始终为0,因此从未使用过

  • args :提供给函数的参数的一对列表。

  • env :调用函数的环境。

checkArity是一个调用Rf_checkArityCall的宏,它基本上查找参数的数量( names.c的第五列是arity)并确保提供的数字匹配。 你必须在C中完成相当多的宏和函数才能看到正在发生的事情 - 拥有一个你可以通过的R源的本地副本是非常有帮助的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM