c - 使用 "NA"将 R 数组传递给 C 函数

标签 c r parameter-passing dynamic-library

我使用 C 库在 R 中工作。我需要将一个数字在 1 到 10 之间的数组传递给 C 函数,但它也可以是“NA”。然后在 C 中,根据我需要设置输出的值。 这是一个简化的代码

heredyn.load("ranking.so")

fun <- function(ranking) {
  nrak <- length(ranking)
  out <- .C("ranking", as.integer(nrak), as.character(ranking), rr = as.integer(vector("integer",nrak)))
  out$rr
}

ranking <- sample(c(NA,seq(1,10)),10,replace=TRUE)
rr <- fun(ranking)

C 函数可以简单地是这样的

#include <R.h>

void ranking(int *nrak, char *ranking, int *rr) {
  int i ;

  for (i=0;i<*nrak;i++) {
    if (ranking[i] == 'NA')
      rr[i] = 1 ;
    else
      rr[i] = (int) strtol(&ranking[i],(char **)NULL,10) ;
  }
}

由于“NA”值,我将排名设置为字符,但也许还有另一种方法可以做到这一点,使用整数并且在调用函数之前不将“NA”替换为 0?

(像这样的代码,总是给我一个零数组...)

最佳答案

使用 R_NaInt 测试该值是否为 NA,例如

#include <R.h>

void ranking_c(int *nrak, int *ranking, int *rr) {
  for (int i=0; i < *nrak; i++)
      rr[i] = R_NaInt == ranking[i] ? -1 : ranking[i];
}

通过明确允许 NA 从 R 调用

> x = c(1:2, NA_integer_)
> .C("ranking_c", length(x), as.integer(x), integer(length(x)), NAOK=TRUE)[[3]]
[1]  1  2 -1

或者,使用 R 的 .Call() 接口(interface)。每个 R 对象都表示为一个 S 表达式。有 C 级函数来操作 S 表达式,例如长度 Rf_length()、数据访问 INTEGER() 和分配 Rf_allocVector() 不同类型的 S 表达式,例如用于整数 vector 的 INTSXP。

R 内存管理使用垃圾收集器,它可以在任何分配内存的调用上运行。因此,最佳做法是 PROTECT() 在范围内的任何 R 分配。

您的函数将接受 0 个或多个 S 表达式作为输入,并返回单个 S 表达式;它可能被实现为

#include <Rinternals.h>
#include <R_ext/Arith.h>

SEXP ranking_call(SEXP ranking)
{
    /* allocate space for result, PROTECTing from garbage collection */
    SEXP result = PROTECT(Rf_allocVector(INTSXP, Rf_length(ranking)));

    /* assign result */
    for (int i = 0; i < Rf_length(ranking); ++i)
        INTEGER(result)[i] =
            R_NaInt == INTEGER(ranking)[i] ? -1 : INTEGER(ranking)[i];

    UNPROTECT(1);               /* no more need to protect */
    return result;
}

并使用 .Call("ranking_call", as.integer(ranking)) 从 R 调用。

使用 .Call 在速度和内存分配方面比 .C 更有效(.C 可能会在途中复制原子 vector ),但主要原因使用它是因为它在直接使用 R 的数据结构方面提供了灵 active 。当返回值比原子 vector 更复杂时,这一点尤其重要。

关于c - 使用 "NA"将 R 数组传递给 C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35638599/

相关文章:

python-3.x - 使用 yaml 覆盖命名空间

c - 关于C中循环语法的问题

使用用户输入 ('+'/'-' ) 进行数学运算的 C 控制台程序不起作用

c - Lua C API - 将数据附加到协程

R Sweave 用户定义函数

r - 如何检查 R 环境是否存在

r - 我如何预测在 R 中使用带有生存包的 AFT 模型?

c - intel intrinsics - 加载/存储的函数指针

java - 方法中数组的值无法返回到 main (java)

c++ - 再次将指针传递给函数时遇到问题