将C ++类/对象转换为Rcpp的最有效方法是什么?

时间:2017-07-02 07:30:29

标签: rcpp

我是Rccp的新手并且通过将C ++代码翻译成Rcpp环境遇到了一个问题 - 到目前为止我找不到解决方案(这是我原来的帖子的编辑版本,我认为不清楚):

背景:我有多个参数和大型矩阵/数组需要转移到C ++级别。在C ++中,我有几个函数需要访问这些参数和矩阵,在某些情况下,更改值等。在C ++中,我将创建组合所有参数和矩阵的类以及需要访问它们的函数。通过这样做,我不需要将它们(每次)传递给函数。

问题:我无法弄清楚这对Rcpp有何影响。在下面的例子中(函数是愚蠢的,但希望是一个简单的方式来说明我的问题),我在R中创建一个矩阵,然后在C ++中使用。但是,然后我将整个矩阵移交给子函数,以便在此函数中使用矩阵。这似乎是一个非常糟糕的想法,我想要在命名空间内存中使用矩阵M并在子函数中访问它而不克隆它。

#include <RcppArmadillo.h>
//[[Rcpp::depends(RcppArmadillo)]]

using namespace Rcpp;


double fnc1 (int t, int s, arma::mat M) // I would prefer not to have M in the arguments but rather available in the namespace
{
 double out = M(t,s) - M(t,s);
 return out;
}


// [[Rcpp::export]]
arma::mat Rout (arma::mat M)
{
 int ncol = M.n_cols;
 int nrow = M.n_rows;

 for(int c = 0; c<ncol; ++c)
 {
  for(int r = 0; r<nrow; ++r)
  {
   M(r,c) =  fnc1(r, c, M);
  }
 }

return M;
}


/*** R
m <- matrix(runif(50), ncol = 10, nrow = 5)
Rout(m)
*/

1 个答案:

答案 0 :(得分:3)

好的,让我们谈谈 R C ++ 。在某些时候,你必须有一个导出 R 的函数,它将接收一个 R 对象并传递它到 C ++ 。一旦进入 C ++ ,天空就是你想要如何构建与该对象的交互的限制。思想过程:

  

但是,然后我将整个矩阵交给一个子函数,以便在此函数中使用矩阵。这似乎是一个非常糟糕的主意,我想在命名空间内存中使用矩阵M并且在子函数中访问它而不克隆它

稍有问题,因为您现在刚刚引入了一个名为 M 全局变量来处理您的数据。如果未初始化 M ,则例程将停滞不前。如果您无意中修改了 M ,那么所有例程的数据都将更改。因此,我不确定全局变量方法是否是您想要的解决方案。

您似乎遇到的主要问题是关于&#34;克隆&#34;的强调部分。使用 C ++ 时,默认的构造传递是复制对象。但是,与 R 不同,通过在&前添加对象名称来通过引用传递非常容易,因此完全否定副本。这使过程本地化。

Pass-by-Reference演示

#include <RcppArmadillo.h>
//[[Rcpp::depends(RcppArmadillo)]]

using namespace Rcpp;


double fnc1 (int t, int s, const arma::mat& M) {
  double out = M(t,s) - M(t,s);
  return out;
}


// [[Rcpp::export]]
arma::mat Rout (arma::mat& M) {
  int ncol = M.n_cols;
  int nrow = M.n_rows;

  for(int c = 0; c<ncol; ++c) {
    for(int r = 0; r<nrow; ++r) {
      M(r,c) =  fnc1(r, c, M);
    }
  }

  return M;
}


/*** R
m <- matrix(runif(50), ncol = 10, nrow = 5)
Rout(m)
*/

全局变量演示

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

// Create a namespace to store M
namespace toad {
 arma::mat M;
}

double fnc1 (int t, int s) 
{
  double out = toad::M(t,s) - toad::M(t,s);
  return out;
}

// [[Rcpp::export]]
void Rin (arma::mat M)
{
 toad::M = M;
}

// [[Rcpp::export]]
void Rmanipulate()
{
  int ncol = toad::M.n_cols;
  int nrow = toad::M.n_rows;

  for(int c = 0; c<ncol; ++c)
  {
    for(int r = 0; r<nrow; ++r)
    {
      toad::M(r,c) =  fnc1(r, c);
    }
  }
}

// [[Rcpp::export]]
arma::mat Rout (){
  return toad::M;
}


/*** R
m <- matrix(runif(50), ncol = 10, nrow = 5)
Rin(m)
Rmanipulate()
Rout()
*/