Rcpp模块:将对成员变量c ++对象的引用返回给R

时间:2017-02-08 22:36:01

标签: rcpp

我有一个C ++类,它将一个指向其自身对象的原始指针存储为成员变量。该类通过Rcpp模块暴露给R.我想通过属性返回对成员变量的引用。但是,似乎返回了副本。

这也适用于将不同成员变量对象返回到R的其他情况。

最小可重复的示例

我使用Rcpp::Rcpp.package.skeleton('testmod', module = TRUE)创建了一个新的骨架包,并添加了我自己的类Foo,将其暴露给R.可以在github上找到here的示例。

src / Foo.cpp的内容:

#include <Rcpp.h>

class Foo;
RCPP_EXPOSED_CLASS(Foo)

class Foo
{
  public:
    Foo():
      ancestor_ptr(NULL){}
    Foo(const Foo& ancestor):
      ancestor_ptr(&ancestor){}

    const Foo& get_ancestor() {return *ancestor_ptr;}

    const Foo* ancestor_ptr;
};


RCPP_MODULE(mymodule){
  using namespace Rcpp ;

  class_<Foo>("Foo")
    .default_constructor()
    .constructor<const Foo&>()
    .property("ancestor", &Foo::get_ancestor)
    ;
}

在R会话中测试给了我:

>library(testmod)
>a <- new(Foo)
>b <- new(Foo, a)
>a
C++ object <0x1c57108> of class 'Foo' <0x22d78b0>
>b$ancestor
C++ object <0x1f8ffa0> of class 'Foo' <0x22d78b0>

所以0x1c57108 != 0x1f8ffa0,我检查了未显示的辅助函数0x1c57108实际上是对象a的地址。

修改 我刚刚在uuid成员变量和自定义拷贝构造函数的帮助下检查了实际上正在制作成员对象的副本。

1 个答案:

答案 0 :(得分:4)

模块无法真正处理返回的引用,因此在调用get_ancestor时正在进行复制。

考虑这个代码的扩展版本:

#include <Rcpp.h>

class Foo;
RCPP_EXPOSED_CLASS(Foo)

  class Foo
  {
  public:
    Foo():
    ancestor_ptr(NULL){}
    Foo(const Foo& ancestor):
      ancestor_ptr(&ancestor)
    {
      Rprintf( "Foo(const Foo&)\n")  ;  
    }

    const Foo& get_ancestor() {return *ancestor_ptr;}
    const Foo* ancestor_ptr;

    void print_ptr(){
      Rprintf( "ptr = %p\n", this ) ;
    }

    void print_ancestor_ptr(){
      Rprintf( "ptr = %p\n", ancestor_ptr ) ;
    }

  };


RCPP_MODULE(mymodule){
  using namespace Rcpp ;

  class_<Foo>("Foo")
    .default_constructor()
    .constructor<const Foo&>()
    .property("ancestor", &Foo::get_ancestor)
    .method( "print_ptr", &Foo::print_ptr )
    .method( "print_ancestor_ptr", &Foo::print_ancestor_ptr )
  ;
}

当您调用复制构造函数时会生成一个副本,这很好,您的意思是:

> a  <- new( Foo )
> b <- new( Foo, a )
Foo(const Foo&)

但是,当你致电get_ancestor时,也会提出一个问题:

> b$ancestor
Foo(const Foo&)
C++ object <0x10204ee00> of class 'Foo' <0x10207c7c0>

然而,在b中你确实存储了正确的指针:

> a$print_ptr()
ptr = 0x113278820
> b$print_ancestor_ptr() 
ptr = 0x113278820