Rcpp 可以公开一个 C++ class 方法引用同一个 class 吗?
Can Rcpp expose a C++ class method taking a reference to the same class?
当 class 有一个成员采用 class 的实例时,是否可以使用 Rcpp 将 C++ class 公开给 R?
示例:
#include <Rcpp.h>
class Test {
public:
Test(int x): x_(x) {}
int getValue() { return x_; }
void addValue(int y) { x_ += y; }
void merge(const Test& rhs) { x_ += rhs.x_; }
private:
int x_;
};
using namespace Rcpp;
RCPP_MODULE(mod_test) {
class_<Test>("Test")
.constructor<int>("sets initial value")
.method("getValue", &Test::getValue, "Returns the value")
.method("addValue", &Test::addValue, "Adds a value")
.method("merge", &Test::merge, "Merges another Test into this object")
;
}
不幸的是,这会导致以下错误:
error: no matching constructor for initialization of 'Test'
在阅读和搜索答案后,我想到了单独包含 RcppCommon.h 然后插入一个块的成语,如下所示:
namespace Rcpp {
template <> Test as( SEXP x ) ;
}
不幸的是,这会导致以下错误:
Error in dyn.load("/.../sourceCpp_86871.so") : unable to load
shared object '/.../sourceCpp_86871.so':
dlopen(/.../sourceCpp_86871.so, 6): Symbol not found:
__ZN4Rcpp2asI4TestEET_P7SEXPREC Referenced from: /.../sourceCpp_86871.so Expected in: flat namespace in
/.../sourceCpp_86871.so
可以这样做吗?
是否有我需要创建的 'as' 专业化的实现?有什么地方可以写的例子吗?
或者,是否有示例说明如何检查 SEXP 并将其转换回 C++ 对象 "wraps"?
正确的 as
转换似乎是通过插入 RCPP_EXPOSED_CLASS
.
生成的
完整的工作示例变为:
#include <Rcpp.h>
class Test {
public:
Test(int x): x_(x) {}
int getValue() { return x_; }
void addValue(int y) { x_ += y; }
void merge(const Test& rhs) { x_ += rhs.x_; }
private:
int x_;
};
using namespace Rcpp;
RCPP_EXPOSED_CLASS(Test)
RCPP_MODULE(mod_test) {
class_<Test>("Test")
.constructor<int>("sets initial value")
.method("getValue", &Test::getValue, "Returns the value")
.method("addValue", &Test::addValue, "Adds a value")
.method("merge", &Test::merge, "Merges another Test into this object")
;
}
现在可以正常工作了:
> Rcpp::sourceCpp('test.cpp')
> a = Test$new(2)
> b = Test$new(3)
> a$getValue()
[1] 2
> a$merge(b)
> a$getValue()
[1] 5
当 class 有一个成员采用 class 的实例时,是否可以使用 Rcpp 将 C++ class 公开给 R?
示例:
#include <Rcpp.h>
class Test {
public:
Test(int x): x_(x) {}
int getValue() { return x_; }
void addValue(int y) { x_ += y; }
void merge(const Test& rhs) { x_ += rhs.x_; }
private:
int x_;
};
using namespace Rcpp;
RCPP_MODULE(mod_test) {
class_<Test>("Test")
.constructor<int>("sets initial value")
.method("getValue", &Test::getValue, "Returns the value")
.method("addValue", &Test::addValue, "Adds a value")
.method("merge", &Test::merge, "Merges another Test into this object")
;
}
不幸的是,这会导致以下错误:
error: no matching constructor for initialization of 'Test'
在阅读和搜索答案后,我想到了单独包含 RcppCommon.h 然后插入一个块的成语,如下所示:
namespace Rcpp {
template <> Test as( SEXP x ) ;
}
不幸的是,这会导致以下错误:
Error in dyn.load("/.../sourceCpp_86871.so") : unable to load shared object '/.../sourceCpp_86871.so':
dlopen(/.../sourceCpp_86871.so, 6): Symbol not found: __ZN4Rcpp2asI4TestEET_P7SEXPREC Referenced from: /.../sourceCpp_86871.so Expected in: flat namespace in /.../sourceCpp_86871.so
可以这样做吗?
是否有我需要创建的 'as' 专业化的实现?有什么地方可以写的例子吗?
或者,是否有示例说明如何检查 SEXP 并将其转换回 C++ 对象 "wraps"?
正确的 as
转换似乎是通过插入 RCPP_EXPOSED_CLASS
.
完整的工作示例变为:
#include <Rcpp.h>
class Test {
public:
Test(int x): x_(x) {}
int getValue() { return x_; }
void addValue(int y) { x_ += y; }
void merge(const Test& rhs) { x_ += rhs.x_; }
private:
int x_;
};
using namespace Rcpp;
RCPP_EXPOSED_CLASS(Test)
RCPP_MODULE(mod_test) {
class_<Test>("Test")
.constructor<int>("sets initial value")
.method("getValue", &Test::getValue, "Returns the value")
.method("addValue", &Test::addValue, "Adds a value")
.method("merge", &Test::merge, "Merges another Test into this object")
;
}
现在可以正常工作了:
> Rcpp::sourceCpp('test.cpp')
> a = Test$new(2)
> b = Test$new(3)
> a$getValue()
[1] 2
> a$merge(b)
> a$getValue()
[1] 5