我正在尝试使用 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 类似的接口(interface),其中 Python 对象仅包含指向 C++ 对象的指针。我觉得很奇怪,Rcpp 试图复制对象来包装它。
有办法解决这个问题吗?是否有可能仅将指向对象的指针包装在 R 类型中,并且仍然以某种方式正确管理其生命周期?我对任何解决方案持开放态度,我不打算使用 Rcpp,它似乎是导出此功能的最简单方法。
最佳答案
到目前为止,我发现的最简单的解决方案是从 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");
}
关于c++ - Rcpp 需要复制构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49785379/