2

假设我有一个名为“packA”的 R 包,其中包含以下文件“funcA.cpp”:

// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::interfaces(r, cpp)]]
#include <RcppArmadillo.h>
using namespace Rcpp;

// [[Rcpp::export]]
void funcA (arma::vec& x) {
  x += 1;
}

从 R 调用此函数会产生将 1 原地添加到向量的每个元素的预期结果:

> vec <- c(1, 2, 3)
> funcA(vec)
> vec
[1] 2 3 4

现在说我有第二个包“packB”,它想调用函数“funcA”。它包含以下名为“funcB.cpp”的文件:

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <packA.h>
using namespace Rcpp;

// [[Rcpp::export]]
void funcB() {
  arma::vec x = {1, 2, 3};

  Rcout << x << "\n";
  packA::funcA(x);
  Rcout << x << "\n";
}

调用此函数不再产生所需的结果,因为看起来向量 x 不再就地修改:

> funcB()
   1.0000
   2.0000
   3.0000

   1.0000
   2.0000
   3.0000

有没有办法在仍然使用 Rcpp 的同时保留 C++ 函数的就地操作?提前感谢您的任何建议。

编辑: 我根据 Dirk Eddelbüttel 的建议修改了“funcB.cpp”:

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <packA.h>
using namespace Rcpp;

// [[Rcpp::export]]
void funcB(arma::vec& y) {
  packA::funcA(y);
}

不幸的是,从 R 调用函数时的结果是相同的:

> vec <- c(1, 2, 3)
> funcB(vec)
> vec
[1] 1 2 3 

编辑 2: 经过一些进一步的实验,我注意到事情一旦arma::vec& x出现在funcA. 只需使用NumericVector作品:

“funcA.cpp”

// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::interfaces(r, cpp)]]
#include <RcppArmadillo.h>
using namespace Rcpp;

// [[Rcpp::export]]
void funcA (NumericVector& num_x) {
  num_x[2] = 10 + num_x[2];
}
> vec <- c(1, 2, 3)
> funcA(vec)
> vec
[1]  1  2 13

“funcB.cpp”

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <packA.h>
using namespace Rcpp;

// [[Rcpp::export]]
void funcB(NumericVector& num_y) {
  packA::funcA(num_y);
}

> vec <- c(1, 2, 3)
> funcB(vec)
> vec
[1]  1  2 13

即使使用高级arma::vec构造函数来创建具有共享内存的犰狳向量,只要输入是 aNumericVector

“funcA.cpp”

// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::interfaces(r, cpp)]]
#include <RcppArmadillo.h>
using namespace Rcpp;

// [[Rcpp::export]]
void funcA (NumericVector& num_x) {
  arma::vec x_int = arma::vec(num_x.begin(), 3, false, false);
  x_int(2) = 10 + x_int(2);
}
> vec <- c(1, 2, 3)
> funcA(vec)
> vec
[1]  1  2 13

> vec <- c(1, 2, 3)
> funcB(vec)
> vec
[1]  1  2 13

尝试相同的事情arma::vec不再有效。

“funcA.cpp”

// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::interfaces(r, cpp)]]
#include <RcppArmadillo.h>
using namespace Rcpp;

// [[Rcpp::export]]
void funcA (arma::vec& x) {
  arma::vec x_int = arma::vec(x.begin(), 3, false, false);
  x(2) = 10 + x(2);
}
> vec <- c(1, 2, 3)
> funcA(vec)
> vec
[1]  1  2 13

“funcB.cpp”

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
#include <packA.h>
using namespace Rcpp;

// [[Rcpp::export]]
void funcB(arma::vec& y) {
  packA::funcA(y);
}
> vec <- c(1, 2, 3)
> funcB(vec)
> vec
[1] 1 2 3
4

1 回答 1

1

我认为这是一个不同的话题。当您调用 时A,您会创建一个 R 向量。那个 R 向量是用 R 内存构造的,R “拥有”它,我们让 Armadillo 重用它。那里是可能的。

但是当你运行时B,你构造了一个不属于 R 的犰狳向量。这不是 R 中的“我们的”内存,内容只能通过副本返回。而你失去了就地模式。使该函数具有arma::vec签名,并改为传递现有向量。

于 2020-08-17T11:22:04.780 回答