【问题标题】:Creating a std::shared_ptr object and returning it to the R side (Rcpp)创建 std::shared_ptr 对象并将其返回到 R 端 (Rcpp)
【发布时间】:2014-10-06 13:18:49
【问题描述】:

我正在尝试使用 Rcpp 为 C++ 脚本编写 R 绑定。其中一个函数需要std::shared_ptr object。我发现很难初始化 std::shared_ptr obj 并将其作为 Rcpp::XPtr 对象返回到 R 端。

我试过了(最小的例子):

#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;
};

但是得到以下错误:

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

关于如何做到这一点的任何想法?还是我做错了?

【问题讨论】:

标签: c++ r rcpp


【解决方案1】:

@d3coy 的回答包含了几乎所有的信息。 Rcpp::XPtr 是一个模板智能指针类,它的参数是指针类,而不是它指向的类。所以Rcpp::XPtr&lt;std::shared_ptr&lt;TestClass&gt;&gt; 将是一个指向std::shared_ptr&lt;TestClass&gt;* 的智能指针。注意*,这很重要。

shared_ptr 超出范围时,如果这是原始指针的最后一个持有者,原始指针可能会被删除。这绝对不是你想要的。

相反,您可以使用new 创建一个原始指针,并用它提供XPtr。当垃圾收集器收集与XPtr 无关的R 对象时,该指针将获得deleted,这是您在处理外部指针时通常想要的。

我知道目前的指导方针是尽可能使用make_uniquemake_shared 而不是new,但在这种情况下你需要new。聪明来自XPtr,如果你把它和shared_ptr混在一起,它们会互相妨碍。

【讨论】:

    【解决方案2】:

    我怀疑 R 端是否期望将 std::shared_ptr 传递给它。我假设您的源代码中的一些其他代码依赖于 std::shared_ptr,但您想将内部原始指针传递给 R。我还假设 std::shared_ptr 的生命周期在您的代码中得到更适当的管理,因为提供的代码会使 std::shared_ptr 在函数之后超出范围并在下一次取消引用时崩溃。

    在任何情况下,如果您只想将内部原始指针传递给 R,您可以这样做(做作):

    //[[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;
    };
    

    【讨论】:

    • 编译器说‘shared_ptr’不是‘std’的成员。它还在工作吗?
    • 启用对 C++11 的支持。
    【解决方案3】:

    感谢所有提示和“指针”。不确定这是否是正确的回应方式,但我想我会输入我找到的解决方案。

    关键是 R 端确实不一定需要std::shared_ptr。但是,我正在与现有的 C++ 库进行交互。我需要实例化库的 std::shared_ptr&lt;TestClass&gt;(使用 R)并反馈到需要 std::shared_ptr&lt;TestClass&gt; 的 C++ 算法中。

    我解决它的方法如下(示例和未经测试):

    #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);
    };
    

    然后在 R 中我可以做到:

    test_container <- get_test_obj()
    do_something_with_shared_ptr_testclass(test_container)
    

    【讨论】:

      猜你喜欢
      • 2020-11-04
      • 1970-01-01
      • 1970-01-01
      • 2012-07-21
      • 2012-08-17
      • 2015-08-30
      • 2016-12-15
      • 2017-03-22
      • 2016-07-15
      相关资源
      最近更新 更多