如何将Rcpp模块导出的类对象回传至C++层调用?
问题根因
你遇到的编译报错和潜在崩溃问题来自两个核心错误:
- 参数类型不匹配Rcpp转换规则:你当前
combine方法的入参是ITestClass值类型,Rcpp要将R侧传入的ITestClass实例(本质是SEXP对象)转换为C++值类型时,找不到对应的ITestClass(SEXP)构造函数,直接抛出编译错误。 - 严重内存管理错误:你在
get_object_ptr中将栈上存储的impl成员地址包装为std::shared_ptr返回,会导致同一块内存被两次释放:一次是shared_ptr计数归零触发的delete,一次是ITestClass对象销毁时自动析构impl成员,属于典型的未定义行为,即使编译通过运行也会崩溃。
修复方案
第一步:修正ITestClass的内存持有逻辑
将impl从值成员改为std::shared_ptr<TestClass>持有,从根源解决内存重复释放问题。
第二步:修改combine方法的入参类型
将入参改为ITestClass*指针类型,Rcpp对模块注册的自定义类默认支持SEXP到类指针的自动转换,不需要额外写转换逻辑。
修改后完整代码
class TestClass { public: TestClass(int const& n, double const& x) : n(n), x(x) {} const double get_x() { return x; } double combine(std::shared_ptr<TestClass> obj) { return x + obj->get_x(); } protected: int n; double x; }; //' @export ITestClass class ITestClass { public: ITestClass(int const& in_n, double const& in_x) : impl(std::make_shared<TestClass>(in_n, in_x)) {} double get_x() { return impl->get_x(); } // 入参改为指针类型,Rcpp自动完成转换 double combine(ITestClass* obj) { return impl->combine(obj->get_object_ptr()); } std::shared_ptr<TestClass> get_object_ptr() { return impl; } private: // 改为shared_ptr持有底层实现 std::shared_ptr<TestClass> impl; }; RCPP_MODULE(RTestClassModule) { class_<ITestClass>("ITestClass") .constructor<int, double>() .method("get_x", &ITestClass::get_x, "get_x") .method("combine", &ITestClass::combine, "combine"); }
R侧调用示例
# 加载你的包后执行 obj1 <- ITestClass$new(1, 2.5) obj2 <- ITestClass$new(2, 3.5) # 返回结果为6,符合预期 obj1$combine(obj2)
内容的提问来源于stack exchange,提问作者Hong Ooi
相关产品推荐
相关产品推荐

