我无法理解如何使用
Rcpp::XPtr
。
我想将整数向量的 R 列表传递给 C++,将其转换为
std::vector<std::unordered_set<int> >
,将其作为 Rcpp::XPtr
返回给 R,并在以后的 C++ 函数中重用它。
// [[Rcpp::plugins(openmp)]]
#include <Rcpp.h>
#include <vector>
#include <unordered_set>
#include <omp.h>
#include <cstddef>
// [[Rcpp::export]]
Rcpp::XPtr<std::vector<std::unordered_set<int> > > convert_to_cpp_type(Rcpp::List& x) {
std::size_t x_size = x.size();
std::vector<std::unordered_set<int> > y(x_size);
for(std::size_t i = 0; i < x_size; ++i) {
Rcpp::IntegerVector x_i = x[i];
y[i].insert(x_i.begin(), x_i.end());
}
Rcpp::XPtr<std::vector<std::unordered_set<int> > > z(y);
return z;
}
// [[Rcpp::export]]
Rcpp::NumericVector use_xptr(SEXP a) {
Rcpp::XPtr<std::vector<std::unordered_set<int> > > b(a);
std::size_t b_size = (*b).size();
std::vector<double> c (b_size);
#pragma omp parallel for num_threads(10)
for(std::size_t i = 0; i < b_size; ++i) {
c[i] = example_function((*b)[i]);
}
return Rcpp::wrap(c);
}
这段代码无法编译,但它应该提供我想要做什么的想法。第二个函数中的
a
是第一个函数导出的XPtr
。
这段代码应该有多个错误。然而,即使在浏览了 Stack Overflow、Rcpp 网站和其他各种网站几个小时后,我仍然不知道如何正确实现这一点。
您的第一个函数无法编译,因为 XPtr 构造函数需要一个原始指针,而不是
std::vector
。但是,返回的指针比无用更糟糕,因为它指向函数返回后超出范围的局部变量。如果您稍后尝试使用它,那么您的会话将会崩溃。
以下函数将返回一个指向
std::vector<std::unordered_set>>
的有效指针:
library(Rcpp)
cppFunction("
Rcpp::XPtr<std::vector<std::unordered_set<int> > >
convert_to_cpp_type(Rcpp::List x) {
typedef std::vector<std::unordered_set<int>> obj;
std::size_t x_size = x.size();
obj* y = new obj;
for(std::size_t i = 0; i < x_size; ++i) {
Rcpp::IntegerVector x_i = x[i];
std::unordered_set s(x_i.begin(), x_i.end());
y->push_back(s);
}
Rcpp::XPtr<obj> z(y);
return z;
}")
要获取指针索引的对象的内容,我们需要再次构建R列表:
cppFunction("
Rcpp::List use_xptr(SEXP a) {
Rcpp::XPtr<std::vector<std::unordered_set<int>>> b(a);
Rcpp::List out;
for(std::size_t i = 0; i < b->size(); ++i) {
Rcpp::NumericVector x_i((*b)[i].begin(), (*b)[i].end());
out.push_back(x_i);
}
return out;
}")
为了完整起见,让我们创建一个可以从 R 调用的函数,该函数修改我们的 C++ 对象(因为我们没有
example_function
cppFunction("
void do_stuff(Rcpp::XPtr<std::vector<std::unordered_set<int>>> x) {
x->push_back(std::unordered_set<int> {0, 1, 2, 3});
return;
}")
现在在 R 中我们可以做:
x <- list(1:10, 3:7)
x
#> [[1]]
#> [1] 1 2 3 4 5 6 7 8 9 10
#>
#> [[2]]
#> [1] 3 4 5 6 7
xptr <- convert_to_cpp_type(x)
xptr
#> <pointer: 0x0000023659ab57c0>
do_stuff(xptr)
use_xptr(xptr)
#> [[1]]
#> [1] 10 9 8 7 6 5 4 3 2 1
#>
#> [[2]]
#> [1] 7 6 5 4 3
#>
#> [[3]]
#> [1] 3 2 1 0
这似乎是一种不必要的困难做事方式。在我看来,将列表发送到 C++,让它执行您想要的所有计算并返回结果更有意义。指针在这里并不能真正帮助你。