7

我用 C 语言编写了一个函数“foo”,我想从 R 程序中调用它。该函数将矩阵作为输入并对其进行一些操作(例如,将每个元素加 1)。虽然很容易将单个向量作为

.C("foo", n=as.integer(5), x=as.double(rnorm(5)))

用 foo 实现为

void foo(int *nin, double *x)
{
int n = nin[0];

int i;

for (i=0; i<n; i++)
    x[i] = x[i] * x[i];
} 

如何传入二维数组?如果我将“double *x”更改为“double **x”,则会出现分段错误。任何指针表示赞赏。

4

3 回答 3

8

放弃.C()并切换到.Call()哪个可以让您将整个 R 对象作为所谓的SEXP对象传递。

您可以通过 R 的 C API 或通过具有(我们认为的)很好的高级抽象的 Rcpp 来解析这些内容。

R> library(inline)  # use version 0.3.10 for rcpp() wrapper
R> 
R> addMat <- rcpp(signature(ms="numeric"), body='
+    Rcpp::NumericMatrix M(ms);
+    Rcpp::NumericMatrix N = Rcpp::clone(M);
+    for (int i=0; i<M.nrow(); i++)
+       for (int j=0; j<M.ncol(); j++) 
+          N(i,j) = M(i,j) + 1;
+    return(N);
+ ')
R> addMat(matrix(1:9,3,3))
     [,1] [,2] [,3]
[1,]    2    5    8
[2,]    3    6    9
[3,]    4    7   10
R> 
于 2012-10-22T03:01:14.577 回答
8

无需放弃.C像这样的直接操作。请记住,R 中的矩阵是向量 + 维度。同样在 C 中,传递矩阵及其维度,并将矩阵的元素作为适当的偏移量访问到向量中。就像是

void cplus1(double *x, int *dim)
{
    for (int j = 0; j < dim[1]; ++j)
        for (int i = 0; i < dim[0]; ++i)
            x[j * dim[0] + i] += 1;
}

所以inline用作一个不错的派对技巧

library(inline)
sig <- signature(x="numeric", dim="integer")
body <- "
    for (int j = 0; j < dim[1]; ++j)
        for (int i = 0; i < dim[0]; ++i)
            x[j * dim[0] + i] += 1;
"

cfun <- cfunction(sig, body=body, language="C", convention=".C")

plus1 <- function(m) {
    m[] = cfun(as.numeric(m), dim(m))$x
    m
}
于 2012-10-22T03:14:05.900 回答
0

使用.C,您必须通过@Martin Morgan 的答案中的附加参数传递矩阵维度。

.Call

SEXP foo(SEXP mat){
  SEXP dims = getAttttrib(mat, R_DimSymbol);
  int nrow = INTEGER(dims)[0];
  int ncol = INTEGER(dims)[1];
  //...
}
于 2018-01-22T10:01:48.103 回答