如何使用Rcpp使执行就地操作的C++函数可用于另一个R包



假设我有一个名为";packA";它包含下面的文件";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++函数的就地操作?提前谢谢你的建议。

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

// [[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& xfuncA的足迹中,事情就会开始崩溃。简单地使用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构造函数来创建具有共享内存的Armadillo向量,只要输入是NumericVector,也能工作

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

我认为这是另一个话题。调用A时,将创建一个R向量。该R矢量由R存储器构成;拥有";我们让Armadillo重复使用。在那里就位是可能的。

但当你运行B时,你构建了一个不属于R的Armadillo向量;我们的";R中的内存,并且内容只能通过副本返回。然后你松开了原位mod。使该函数具有arma::vec签名,并传递现有向量。

最新更新