从R中的嵌入式c ++函数返回值

时间:2013-06-23 10:53:33

标签: c++ r rcpp inline-code

我有一些R代码,这有点慢,所以我一直在尝试使用'inline'库直接在R代码中编写一些c ++代码。

这很好用,我现在正试图调整它。

如果我在R中分配'results'数据结构并将它们作为函数参数传递给c函数,我只能使它工作。我想知道是否可以在R代码中使用非void c / c ++函数,这样就可以从c / c ++而不是R中分配和返回内存。

见下面的例子:

library(inline)
cppSig <- signature(res="numeric",ary="numeric",len="integer")
cppBody <- "
int lens=len[0];
res[0]=0;
  for(int j=0;j<lens;j++)
     res[0] += ary[j];
res[0] /= (double) lens;
#if 0 //Is something like this possible? 
    double *rary = new double[lens];
    for(int i=0;i<lens;i++) rary[i] = ary[i]-res[0];
    return rary;
#endif
"
cfun <- cfunction( sig=list(myMean=cppSig), 
                 body=list(cppBody),verbose=T, 
                 convention=".C", cxxargs="-O3", cppargs="-O3",language="C++")
cfunWrap <- function(x)
  cfun$myMean(res=0,ary=x,length(x))$res


cfunWrap(x=rnorm(100))

由于

1 个答案:

答案 0 :(得分:3)

我会做一些不同的事情,特别是在Rcpp文档中只是偶然一眼之后。所以这里只是一个快速列表:

  1. 是的,我们可以让循环更快。通常很多。
  2. 是的,我们可以返回原子C / C ++类型以及向量。有很多例子。一个人使用wrap()来表示这些非矢量类型; double的向量会自动返回。但是你永远不会使用new / delete。有关原因,请参阅Writing R Extensions
  3. 是的,您可以使用内联包。我们经常使用它。但我们从不将其与.C()中的cfunction()调用约定一起使用。 始终使用cxxfunction(),或者至少启用.Call()。我不确定你是怎么错过的。
  4. 由于Rcpp 0.10.0,我们有'Rcpp Attributes',它比内联及其cxxfunction()更容易使用。例如,查看sourceCpp()cppFunction(),或者阅读小插图。
  5. 最后,你真的错过了一些基本的东西。您是否阅读过pdf插图Rcpp-iintroduction和/或Rcpp-FAQ?
  6. 编辑:好的,这是一个完整的示例,跟随您的函数结构(但我们可以做得更好,请参阅下面的内容):

    #include <Rcpp.h>
    
    using namespace Rcpp; 
    
    // [[Rcpp::export]]
    NumericVector monkey(NumericVector ary) {
      int lens = ary.length();   // objects can tell you about their length
      double res=0;
      for(int j=0;j<lens;j++) res += ary[j];
      res /= (double) lens;
    
      NumericVector rary(lens);
      for(int i=0;i<lens;i++) rary[i] = ary[i]-res;
      return rary;
    }
    
    // and we even include some R code to test automagically
    
    /*** R
    set.seed(42)
    x <- rnorm(5)   # just five to keep printout short
    monkey(x)
    cat("Check:")
    x - mean(x)
    */
    

    ,如果你调用它,也会在底部运行R代码:

    R> Rcpp::sourceCpp('/tmp/monkey.cpp')
    
    R> set.seed(42)
    
    R> x <- rnorm(5)   # just five to keep printout short
    
    R> monkey(x)
    [1]  0.9296545 -1.0060021 -0.0781755  0.1915587 -0.0370356
    
    R> cat("Check:")
    Check:
    R> x - mean(x)
    [1]  0.9296545 -1.0060021 -0.0781755  0.1915587 -0.0370356
    R>
    

    但是Rcpp 的关键功能之一就是你甚至可以在C ++中进行向量操作:

    R> cppFunction('NumericVector monkey2(NumericVector x) { return x - mean(x); }')
    R> monkey2(x)
    [1]  0.9296545 -1.0060021 -0.0781755  0.1915587 -0.0370356
    R> 
    

    刚刚编译了一个新的单行C ++函数,它在整个向量x 上运行并运行它。