Creating a std::shared_ptr object and returning it to the R side (Rcpp)

ぃ、小莉子 提交于 2019-12-21 21:13:13

问题


I'm trying to write a R bindings for a C++ script using Rcpp. One of the functions expects a std::shared_ptr object. I find it difficult to initialize the std::shared_ptr obj and return it to the R side as a Rcpp::XPtr object.

I've tried (minimal example):

#include <iostream>
#include <memory>
#include <Rcpp.h> 
using namespace Rcpp;
using std::cout;


class TestClass {
  public:
    int value;

    TestClass(int initial_val) {
      value = initial_val;
    };

};


//[[Rcpp::export]]
SEXP get_test_obj() {
  Rcpp::XPtr<std::shared_ptr<TestClass>> ptr(std::make_shared<TestClass>(5), true);
  return ptr;
};

But get the following error:

 no matching function for call to 'Rcpp::XPtr<std::shared_ptr<TestClass> >::XPtr(std::shared_ptr<TestClass>, bool)'

Any ideas on how to do this? Or am I going about this wrong?


回答1:


I doubt that the R side would expect to have a std::shared_ptr passed to it. I'm assuming that some other code in your source relies on std::shared_ptr, but you want to pass the inner raw pointer to R. I'm also assuming that the std::shared_ptr's lifetime is more appropriately managed in your code, since the code as presented would make the std::shared_ptr fall out of scope after the function and crash on the next dereference.

In any case, if you wanted to just pass the inner raw pointer to R, you'd do it like this (contrived):

//[[Rcpp::export]]
SEXP get_test_obj() {
  std::shared_ptr<TestClass> s_ptr = std::make_shared<TestClass>(5);
  Rcpp::XPtr<TestClass> x_ptr(s_ptr.get(), true);
  return x_ptr;
};



回答2:


The answer from @d3coy has pretty much all the information. Rcpp::XPtr is a template smart pointer class, it's parameter is the pointee class, not the class it points to. So a Rcpp::XPtr<std::shared_ptr<TestClass>> would be a smart pointer to a std::shared_ptr<TestClass>*. Note the *, that's the important bit.

When a shared_ptr goes out of scope, if that's the last holder of the raw pointer, the raw pointer might get deleted. That's definitely not what you want.

Instead you can create a raw pointer with new and feed XPtr with that. This pointer will get deleted when the garbage colector collects the R object undelying the XPtr, which is what you usually want when you deal with external pointers.

I know the current guidelines is to use make_unique and make_shared as much as possible instead of new but in this case you need new. The smartness comes from XPtr, if you mix it with shared_ptr they will get in the way of each other.




回答3:


Thanks for all the tips and 'pointers'. Not sure if this is the correct way to respond, but I thought I'd enter the solution that I found.

The point is that the R side indeed doesn't necessarily require the std::shared_ptr. However I'm interfacing with an existing C++ library. I need to instantiate a std::shared_ptr<TestClass> of the library (using R) and feed in back into the C++ algorithm which expects a std::shared_ptr<TestClass>.

The way I solved it is as follows (example and untested):

#include <iostream>
#include <memory>
#include <Rcpp.h> 
using namespace Rcpp;
using std::cout;


class TestClass {
  public:
  int value;
  TestClass(int initial_val): value(initial_val) {}

};

class TestClassContainer {
  public
  std::shared_ptr<TestClass> test_class_obj;
  TestClassContainer(): test_class_obj(std::make_shared<TestClass>()) {} 
};

//[[Rcpp::export]]
SEXP get_test_obj() {
  Rcpp::XPtr<TestClassContainer> ptr(new TestClassContainer(), true);
  return ptr;
};

//[[Rcpp::export]]
SEXP do_something_with_shared_ptr_testclass(SEXP test_container_obj) {
  Rcpp::XPtr<ResourceContainer> test_ptr(test_container_obj);
  ExternalLib::do_function(test_container_obj->test_class_obj);
};

Then in R I can do:

test_container <- get_test_obj()
do_something_with_shared_ptr_testclass(test_container)


来源:https://stackoverflow.com/questions/26217102/creating-a-stdshared-ptr-object-and-returning-it-to-the-r-side-rcpp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!