我正在尝试使用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)'
关于如何做到这一点的任何想法?或者我错了吗?
答案 0 :(得分:6)
来自@ d3coy的回答几乎包含所有信息。 Rcpp::XPtr
是一个模板智能指针类,它的参数是指针类,而不是它指向的类。因此Rcpp::XPtr<std::shared_ptr<TestClass>>
是指向std::shared_ptr<TestClass>*
的智能指针。请注意*
,这是重要的一点。
当shared_ptr
超出范围时,如果它是原始指针的最后一个持有者,则原始指针可能会被删除。这绝对不是你想要的。
相反,您可以使用new
创建一个原始指针,并使用XPtr
提供delete
。当垃圾邮件收集器收集R对象时,该指针将获得XPtr
d,而make_unique
不是,这是您在处理外部指针时通常需要的。
我知道当前的指南是尽可能使用make_shared
和new
而不是new
,但在这种情况下,您需要XPtr
。智慧来自shared_ptr
,如果你将它与{{1}}混合,它们将会阻碍彼此。
答案 1 :(得分:5)
我怀疑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;
};
答案 2 :(得分:2)
感谢所有的提示和'指针'。不确定这是否是正确的回应方式,但我想我会输入我找到的解决方案。
关键是R方确实不一定需要std::shared_ptr
。但是,我正在与现有的C ++库连接。我需要实例化库的std::shared_ptr<TestClass>
(使用R)并反馈到需要std::shared_ptr<TestClass>
的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)