new_CppObject_xp 将 Rcpp 对象传递给另一个对象时错误地报告错误

new_CppObject_xp incorrectly reports an error when passing an Rcpp object to another

我有两个 Rcpp-wrapped 类、ABA 的构造函数从其参数中提取了一些信息,并将其打印出来以证明它有效。

BA 的对象作为构造函数参数 — 并报告错误,就好像 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::wrapRcpp::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)
*/