R .C interface: Passing multidimensional arrays R .C interface: Passing multidimensional arrays arrays arrays

R .C interface: Passing multidimensional arrays


No need to give up on .C for straight-forward manipulations like this. Remember that a matrix in R is a vector + dimensions. Likewise in C, so pass the matrix and its dimensions, and access elements of the matrix as appropriate offsets into a vector. Something like

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

so using inline as a nice party trick

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}


Give up on .C() and switch to .Call() which lets you pass whole R objects as so-called SEXP objects.

You can parse those the hard way via the C API of R, or via Rcpp with (what we think) nice higher-level abstractions.

R> library(inline)  # use version 0.3.10 for rcpp() wrapperR> 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   10R> 


With .C, you have to pass matrix dimension by additional parameters as in @Martin Morgan's answer.

With .Call

SEXP foo(SEXP mat){  SEXP dims = getAttttrib(mat, R_DimSymbol);  int nrow = INTEGER(dims)[0];  int ncol = INTEGER(dims)[1];  //...}