7

Rプログラムから呼び出したい関数「foo」をCで作成しました。この関数は行列を入力として受け取り、それに対していくつかの操作を行います (たとえば、各要素に 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];
} 

2 次元配列を渡すにはどうすればよいですか? 「double *x」を「double **x」に変更すると、セグメンテーション違反が発生します。任意のポインタをいただければ幸いです。

4

3 に答える 3

8

あきらめて、Rオブジェクト全体をいわゆるオブジェクトとして渡すことができるもの.C()に切り替えます。 .Call()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 に答える