Rcpp 模块:将对成员变量 c++ 对象的引用返回给 R
Rcpp modules: Returning a reference to a member variable c++ object to R
我有一个 C++ class,它将指向同类对象的原始指针存储为成员变量。 class 通过 Rcpp 模块暴露给 R。我想 return 通过 属性 对成员变量的引用。但是,副本似乎是 returned.
这也适用于将不同的成员变量对象 returned 到 R 的其他情况。
最小可重现示例
我使用 Rcpp::Rcpp.package.skeleton('testmod', module = TRUE)
创建了一个新的骨架包并添加了我自己的 class Foo
,将其暴露给 R。示例可以在 here 上找到 github.
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 成员变量和自定义复制构造函数的帮助下进行了检查,实际上正在制作成员对象的副本。
实际情况是模块无法真正处理返回的引用,因此在调用 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
我有一个 C++ class,它将指向同类对象的原始指针存储为成员变量。 class 通过 Rcpp 模块暴露给 R。我想 return 通过 属性 对成员变量的引用。但是,副本似乎是 returned.
这也适用于将不同的成员变量对象 returned 到 R 的其他情况。
最小可重现示例
我使用 Rcpp::Rcpp.package.skeleton('testmod', module = TRUE)
创建了一个新的骨架包并添加了我自己的 class Foo
,将其暴露给 R。示例可以在 here 上找到 github.
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 成员变量和自定义复制构造函数的帮助下进行了检查,实际上正在制作成员对象的副本。
实际情况是模块无法真正处理返回的引用,因此在调用 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