我尝试使用Rcpp将一些C ++ 11功能导出到R.其中一些函数使用std::unique_ptr
返回结果。这个东西无法复制。下面的MCVE使用std::unique_ptr<std::string>
来说明错误。
我在unique_ptr
周围创建了一个类,希望能让所有这些成为可能,但无济于事。这是下面的PtrClassOwner
。函数createClassWrapper
调用原始createClass
,将unique_ptr
粘贴到PtrClassOwner
对象中。
#include <RcppCommon.h>
#include <memory>
#include <string>
// Stuff to wrap:
using PtrClass = std::unique_ptr<std::string>;
PtrClass createClass() { return PtrClass{new std::string("boo")}; }
// ---
class PtrClassOwner {
public:
PtrClass string;
};
PtrClassOwner createClassWrapper() { return PtrClassOwner{createClass()}; }
RCPP_EXPOSED_WRAP(PtrClassOwner); // Rcpp-extending vignette says RCPP_EXPORT_WRAP, which doesn't exist.
RCPP_EXPOSED_AS(PtrClassOwner);
#include <Rcpp.h>
RCPP_MODULE(Class){
using namespace Rcpp;
class_<PtrClassOwner>("PtrClass");
function("createClass", &createClassWrapper);
}
这是GCC报告的第一个错误(v 5.4,在Linux上):
In file included from /home/cris/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/RcppCommon.h:195:0,
from rcpp_module.cpp:1:
/home/cris/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/Rcpp/internal/wrap.h: In instantiation of ‘SEXPREC* Rcpp::internal::wrap_dispatch(const T&, Rcpp::traits::wrap_type_module_object_tag) [with T = PtrClassOwner; SEXP = SEXPREC*]’:
/home/cris/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/Rcpp/internal/wrap_end.h:30:38: required from ‘SEXPREC* Rcpp::wrap(const T&) [with T = PtrClassOwner; SEXP = SEXPREC*]’
/home/cris/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/Rcpp/internal/wrap_end.h:35:20: required from ‘SEXPREC* Rcpp::module_wrap_dispatch(const T&, Rcpp::traits::normal_wrap_tag) [with T = PtrClassOwner; SEXP = SEXPREC*]’
/home/cris/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/Rcpp/internal/wrap.h:922:40: required from ‘SEXPREC* Rcpp::module_wrap(const T&) [with T = PtrClassOwner; SEXP = SEXPREC*]’
/home/cris/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/Rcpp/module/Module_generated_CppFunction.h:34:50: required from ‘SEXPREC* Rcpp::CppFunction0<RESULT_TYPE>::operator()(SEXPREC**) [with RESULT_TYPE = PtrClassOwner; SEXP = SEXPREC*]’
rcpp_module.cpp:26:1: required from here
/home/cris/R/x86_64-pc-linux-gnu-library/3.2/Rcpp/include/Rcpp/internal/wrap.h:759:54: error: use of deleted function ‘PtrClassOwner::PtrClassOwner(const PtrClassOwner&)’
return Rcpp::internal::make_new_object<T>(new T(object));
^
rcpp_module.cpp:9:7: note: ‘PtrClassOwner::PtrClassOwner(const PtrClassOwner&)’ is implicitly deleted because the default definition would be ill-formed:
class PtrClassOwner {
^
问题似乎是,要将对象包装到R对象中,需要复制它。 This other question来自遇到类似问题的人,但没有答案。
我创建了一个类似Python的接口,其中Python对象只包含一个指向C ++对象的指针。我觉得很奇怪,Rcpp试图复制对象来包装它。
有没有解决这个问题的方法?是否有可能只包含一个指向R类型对象的指针,并以某种方式仍然正确地管理它的生命周期?我对任何解决方案持开放态度,我没有开始使用Rcpp,它似乎是导出此功能最直接的方法。
答案 0 :(得分:3)
我到目前为止找到的最简单的解决方案是从std::unique_ptr
中提取指针并从中创建std::shared_ptr
。 Rcpp将包装它,因为它可以被复制。
#include <Rcpp.h>
#include <memory>
#include <string>
// Stuff to wrap:
using PtrClass = std::unique_ptr<std::string>;
PtrClass createClass() { return PtrClass{new std::string("boo")}; }
// ---
using ShPtrClass = std::shared_ptr<PtrClass::element_type>;
class PtrClassOwner {
public:
ShPtrClass shPtrClass;
PtrClassOwner(PtrClass ptr) : shPtrClass(ptr.release()) {}
};
PtrClassOwner createClassWrapper() { return PtrClassOwner{createClass()}; }
std::string getString(PtrClassOwner const& ptr) {
return *(ptr.shPtrClass);
}
RCPP_EXPOSED_CLASS(PtrClassOwner);
RCPP_MODULE(Class){
using namespace Rcpp;
class_<PtrClassOwner>("PtrClass");
function("createClass", &createClassWrapper, "createClass method");
function("getString", &getString, "getString method");
}