c++ 如何使用XPtr

gz5pxeao  于 2024-01-09  发布在  其他
关注(0)|答案(1)|浏览(154)

我很难理解如何使用Rcpp::XPtr
我想将一个R整数向量列表传递给C++,将其转换为std::vector<std::unordered_set<int> >,将其作为Rcpp::XPtr返回给R,并在以后的C++函数中重用它。

  1. // [[Rcpp::plugins(openmp)]]
  2. #include <Rcpp.h>
  3. #include <vector>
  4. #include <unordered_set>
  5. #include <omp.h>
  6. #include <cstddef>
  7. // [[Rcpp::export]]
  8. Rcpp::XPtr<std::vector<std::unordered_set<int> > > convert_to_cpp_type(Rcpp::List& x) {
  9. std::size_t x_size = x.size();
  10. std::vector<std::unordered_set<int> > y(x_size);
  11. for(std::size_t i = 0; i < x_size; ++i) {
  12. Rcpp::IntegerVector x_i = x[i];
  13. y[i].insert(x_i.begin(), x_i.end());
  14. }
  15. Rcpp::XPtr<std::vector<std::unordered_set<int> > > z(y);
  16. return z;
  17. }
  18. // [[Rcpp::export]]
  19. Rcpp::NumericVector use_xptr(SEXP a) {
  20. Rcpp::XPtr<std::vector<std::unordered_set<int> > > b(a);
  21. std::size_t b_size = (*b).size();
  22. std::vector<double> c (b_size);
  23. #pragma omp parallel for num_threads(10)
  24. for(std::size_t i = 0; i < b_size; ++i) {
  25. c[i] = example_function((*b)[i]);
  26. }
  27. return Rcpp::wrap(c);
  28. }

字符串
这段代码不能编译,但它应该提供了我的目标是做什么的想法。第二个函数中的a是第一个函数导出的XPtr
在这段代码中应该有多个错误。然而,即使在浏览了几个小时的Stack Overflow,Rcpp网站和其他各种网站之后,我也没有弄清楚如何正确实现这一点。

qv7cva1a

qv7cva1a1#

你的第一个函数不能编译,因为XPtr构造函数需要一个原始指针,而不是一个std::vector。然而,返回的指针将比无用更糟糕,因为它指向一个在函数返回后超出范围的局部变量。如果你稍后尝试使用它,那么你的会话将崩溃。
下面的函数将返回一个指向std::vector<std::unordered_set>>的有效指针:

  1. library(Rcpp)
  2. cppFunction("
  3. Rcpp::XPtr<std::vector<std::unordered_set<int> > >
  4. convert_to_cpp_type(Rcpp::List x) {
  5. typedef std::vector<std::unordered_set<int>> obj;
  6. std::size_t x_size = x.size();
  7. obj* y = new obj;
  8. for(std::size_t i = 0; i < x_size; ++i) {
  9. Rcpp::IntegerVector x_i = x[i];
  10. std::unordered_set s(x_i.begin(), x_i.end());
  11. y->push_back(s);
  12. }
  13. Rcpp::XPtr<obj> z(y);
  14. return z;
  15. }")

字符串
为了得到指针所索引的对象的内容,我们需要再次构建一个R列表:

  1. cppFunction("
  2. Rcpp::List use_xptr(SEXP a) {
  3. Rcpp::XPtr<std::vector<std::unordered_set<int>>> b(a);
  4. Rcpp::List out;
  5. for(std::size_t i = 0; i < b->size(); ++i) {
  6. Rcpp::NumericVector x_i((*b)[i].begin(), (*b)[i].end());
  7. out.push_back(x_i);
  8. }
  9. return out;
  10. }")


为了完整起见,让我们创建一个函数,我们可以从R调用它来修改我们的C++对象(因为我们没有example_function

  1. cppFunction("
  2. void do_stuff(Rcpp::XPtr<std::vector<std::unordered_set<int>>> x) {
  3. x->push_back(std::unordered_set<int> {0, 1, 2, 3});
  4. return;
  5. }")


在R中,我们可以做:

  1. x <- list(1:10, 3:7)
  2. x
  3. #> [[1]]
  4. #> [1] 1 2 3 4 5 6 7 8 9 10
  5. #>
  6. #> [[2]]
  7. #> [1] 3 4 5 6 7
  8. xptr <- convert_to_cpp_type(x)
  9. xptr
  10. #> <pointer: 0x0000023659ab57c0>
  11. do_stuff(xptr)
  12. use_xptr(xptr)
  13. #> [[1]]
  14. #> [1] 10 9 8 7 6 5 4 3 2 1
  15. #>
  16. #> [[2]]
  17. #> [1] 7 6 5 4 3
  18. #>
  19. #> [[3]]
  20. #> [1] 3 2 1 0


这似乎是一个不必要的困难的方式来做的事情.在我看来,更有意义的是发送一个列表到C++,让它做你想要的所有计算,并返回结果.指针并没有真正帮助你在这里.

展开查看全部

相关问题