new_CppObject_xp 将 Rcpp 对象传递给另一个对象时错误地报告错误
new_CppObject_xp incorrectly reports an error when passing an Rcpp object to another
我有两个 Rcpp-wrapped 类、A
和 B
。 A
的构造函数从其参数中提取了一些信息,并将其打印出来以证明它有效。
B
将 A
的对象作为构造函数参数 — 并报告错误,就好像 A
的构造函数中的提取失败一样。但是由于 A
确实打印出了提取的数据,所以它不会失败。
如何让 B
接受 A
作为参数而不出错?
最小可重现示例:
library(Rcpp)
Rcpp::sourceCpp(code='
#include <Rcpp.h>
struct A {
Rcpp::NumericVector y;
A(Rcpp::List x)
: y(Rcpp::as<Rcpp::NumericVector>(x["foo"]))
{
Rcpp::Rcout << y;
}
};
struct B {
B(A x) { }
};
RCPP_MODULE(A) {
Rcpp::class_<A>("A")
.constructor<Rcpp::List>();
}
RCPP_MODULE(B) {
Rcpp::class_<B>("B")
.constructor<A>();
}
')
Aobj <- new(A, list(foo=1:3))
Bobj <- new(B, Aobj)
输出:
> source('testcase.R', echo=TRUE)
> library(Rcpp)
> Rcpp::sourceCpp(code='
+ #include <Rcpp.h>
+
+ struct A {
+ Rcpp::NumericVector y;
+
+ A(Rcpp::List x)
+ : y(Rcpp::as<Rcpp::NumericVector> .... [TRUNCATED]
> Aobj <- new(A, list(foo=1:3))
1 2 3
> Bobj <- new(B, Aobj)
Error in new_CppObject_xp(fields$.module, fields$.pointer, ...) :
Index out of bounds: [index='foo'].
>
当出现问题时,最好(重新)阅读一些文档。具体来说,Rcpp Extending (PDF),第 3.2.
节
我在 C++ 代码的开头添加了以下内容:
#include <RcppCommon.h>
struct A;
RCPP_EXPOSED_CLASS(A);
…现在工作正常。我承认我还没有完全理解这里发生了什么,但是这个解决方案解决了 MWE 和我的原始代码问题。
我将尝试解释为什么 有效。使用 RCPP_MODULE(A)
,您将 C++ 结构 A
作为 R 中的引用 class 公开。这是自动完成的。但是,当您调用 Bobj <- new(B, Aobj)
时,没有关于如何从该引用 class 转换为所需的 C++ 结构的信息。通过使用 RCPP_EXPOSED_CLASS(A)
,您正在创建 Rcpp::wrap
和 Rcpp::as
的特化,以两种方式在 C++ 和 R 对象之间进行转换。由于我们只缺少 R 到 C++ 的转换,即 Rcpp::as
,因此以下内容也足够了:
#include <RcppCommon.h>
struct A;
RCPP_EXPOSED_AS(A)
#include <Rcpp.h>
struct A {
Rcpp::NumericVector y;
A(Rcpp::List x)
: y(Rcpp::as<Rcpp::NumericVector>(x["foo"]))
{
Rcpp::Rcout << y;
}
};
struct B {
B(A x) { }
};
RCPP_MODULE(A) {
Rcpp::class_<A>("A")
.constructor<Rcpp::List>();
}
RCPP_MODULE(B) {
Rcpp::class_<B>("B")
.constructor<A>();
}
/*** R
Aobj <- new(A, list(foo=1:3))
Bobj <- new(B, Aobj)
*/
我有两个 Rcpp-wrapped 类、A
和 B
。 A
的构造函数从其参数中提取了一些信息,并将其打印出来以证明它有效。
B
将 A
的对象作为构造函数参数 — 并报告错误,就好像 A
的构造函数中的提取失败一样。但是由于 A
确实打印出了提取的数据,所以它不会失败。
如何让 B
接受 A
作为参数而不出错?
最小可重现示例:
library(Rcpp)
Rcpp::sourceCpp(code='
#include <Rcpp.h>
struct A {
Rcpp::NumericVector y;
A(Rcpp::List x)
: y(Rcpp::as<Rcpp::NumericVector>(x["foo"]))
{
Rcpp::Rcout << y;
}
};
struct B {
B(A x) { }
};
RCPP_MODULE(A) {
Rcpp::class_<A>("A")
.constructor<Rcpp::List>();
}
RCPP_MODULE(B) {
Rcpp::class_<B>("B")
.constructor<A>();
}
')
Aobj <- new(A, list(foo=1:3))
Bobj <- new(B, Aobj)
输出:
> source('testcase.R', echo=TRUE)
> library(Rcpp)
> Rcpp::sourceCpp(code='
+ #include <Rcpp.h>
+
+ struct A {
+ Rcpp::NumericVector y;
+
+ A(Rcpp::List x)
+ : y(Rcpp::as<Rcpp::NumericVector> .... [TRUNCATED]
> Aobj <- new(A, list(foo=1:3))
1 2 3
> Bobj <- new(B, Aobj)
Error in new_CppObject_xp(fields$.module, fields$.pointer, ...) :
Index out of bounds: [index='foo'].
>
当出现问题时,最好(重新)阅读一些文档。具体来说,Rcpp Extending (PDF),第 3.2.
节我在 C++ 代码的开头添加了以下内容:
#include <RcppCommon.h>
struct A;
RCPP_EXPOSED_CLASS(A);
…现在工作正常。我承认我还没有完全理解这里发生了什么,但是这个解决方案解决了 MWE 和我的原始代码问题。
我将尝试解释为什么 RCPP_MODULE(A)
,您将 C++ 结构 A
作为 R 中的引用 class 公开。这是自动完成的。但是,当您调用 Bobj <- new(B, Aobj)
时,没有关于如何从该引用 class 转换为所需的 C++ 结构的信息。通过使用 RCPP_EXPOSED_CLASS(A)
,您正在创建 Rcpp::wrap
和 Rcpp::as
的特化,以两种方式在 C++ 和 R 对象之间进行转换。由于我们只缺少 R 到 C++ 的转换,即 Rcpp::as
,因此以下内容也足够了:
#include <RcppCommon.h>
struct A;
RCPP_EXPOSED_AS(A)
#include <Rcpp.h>
struct A {
Rcpp::NumericVector y;
A(Rcpp::List x)
: y(Rcpp::as<Rcpp::NumericVector>(x["foo"]))
{
Rcpp::Rcout << y;
}
};
struct B {
B(A x) { }
};
RCPP_MODULE(A) {
Rcpp::class_<A>("A")
.constructor<Rcpp::List>();
}
RCPP_MODULE(B) {
Rcpp::class_<B>("B")
.constructor<A>();
}
/*** R
Aobj <- new(A, list(foo=1:3))
Bobj <- new(B, Aobj)
*/