15

Rcpp モジュールには次の問題があります: Rcpp モジュールに 2 つのクラスがあるとします。

class A {
  public:
    int x;
};

class B
  public:
    A get_an_a(){
      A an_a();
      an_a.x=3;
      return an_a;
    }
};

RCPP_MODULE(mod){
  using namespace Rcpp ;
  class_<A>("A")
   .constructor()
   .property("x",&A::get_x)
  ;
  class_<B>("B)
   .constructor()
   .method("get_an_A",&get_an_a)
  ;
}

.

現在、A の戻り値の型をどう処理するかわからないため、コンパイルは失敗します。

Rcpp::Xptr で何かできると思ったのですが、Rcpp がクラス A 用に生成した S4 構造体に接続できません。実際には、R のメソッドから外部ポインター オブジェクトを取得します。

2 番目のクラスのメソッドから正しくラップされたオブジェクトを取得する可能性はありますか?

ありがとう、トーマス

[編集]

Dirk の回答によると、ラップされた S4 オブジェクトを作成できるラッパーを作成しました。

template <> SEXP wrap(const A &obj) { // insprired from "make_new_object" from Rcpp/Module.h
  Rcpp::XPtr<A> xp( new A(obj), true ) ; // copy and mark as finalizable
  Function maker=Environment::Rcpp_namespace()[ "cpp_object_maker"];
  return maker ( typeid(A).name() , xp );
}

それでも、メソッド/関数へのパラメーターとしてオブジェクトを戻す方法がわかりません。以下は機能していません。

template <> A* as( SEXP obj){
  Rcpp::List l(obj);
  Rcpp::XPtr<A> xp( (SEXP) l[".pointer"] );
  return (A*) xp;
}

では、パラメーター リストで SEXP として提供される S4 オブジェクトから C++ オブジェクトへの外部ポインターを取得するにはどうすればよいでしょうか。

4

3 に答える 3

13

この機能は Rcpp 0.10.0 で追加されました。

コードがコンパイルされなかった理由は他にもあります。以下のコードは私のために働きます:

class A {
  public:
    A(int x_) : x(x_){}

    int x;
};

class B {
  public:
    A get_an_a(){
      A an_a(3);
      return an_a;
    }
};
RCPP_EXPOSED_CLASS(A)
RCPP_EXPOSED_CLASS(B)

RCPP_MODULE(stackmod){
  using namespace Rcpp ;
  class_<A>("A")
   .constructor<int>()
   .field("x",&A::x)
  ;
  class_<B>("B")
   .constructor()
   .method("get_an_A",&B::get_an_a)
  ;
}

支払う代償は、RCPP_EXPOSED_CLASS次のすべてのクラスに対してマクロを呼び出すことです。

  • モジュールの1つが公開されています
  • 公開されたメソッドの結果として、またはパラメーターとして使用したい

これで、私は得る:

> b <- new( B )
> b$get_an_A( )
C++ object <0x10330a9d0> of class 'A' <0x1006f46e0>
> b$get_an_A( )$x
[1] 3
于 2012-10-25T08:22:16.867 に答える
3

ラッパーを書けば可能です。それらはマナのように空から降ってくるものではありません。それを提供してコンパイラを支援する必要があり、それが選択されます。

RcppBDT の簡単な例:

template <> SEXP wrap(const boost::gregorian::date &d) {
    // convert to y/m/d struct
    boost::gregorian::date::ymd_type ymd = d.year_month_day();     
    return Rcpp::wrap(Rcpp::Date( ymd.year, ymd.month, ymd.day ));
}

ここでは、Boost のクラスが Rcpp クラス (Date) に変換されて返されます (さらに明示的なラップが必要です)。より複雑なクラスには、より複雑なコンバーターが必要です。

編集:そしてもちろん、R から呼び出し可能なものはすべてSEXP foo(SEXP a, SEXP b, ...).Call().

于 2012-09-13T12:07:11.427 に答える
1

わかりました、私はそれを手に入れたと思います。しかし、保証はありません。Dirk の回答によると、ラップされた S4 オブジェクトを作成できるラッパーを作成しました。

template <> SEXP wrap(const A &obj) { // insprired from "make_new_object" from Rcpp/Module.h
  Rcpp::XPtr<A> xp( new A(obj), true ) ; // copy and mark as finalizable
  Function maker=Environment::Rcpp_namespace()[ "cpp_object_maker"];
  return maker ( typeid(A).name() , xp );
}

メソッドがパラメーターとしてオブジェクト (ここではそのオブジェクトへのポインター) を想定している場合、次の "as" ラッパーが役立つ場合があります。

template <> A* as( SEXP obj){
  Rcpp::Environment e(obj);
  Rcpp::XPtr<A> xp( (SEXP) e.get(".pointer") );
  return (A*) xp;
}

もちろん、非ポインターをパラメーターとして使用できる *xp を返すこともできますが、これもオブジェクトをコピーします。

于 2012-09-17T11:21:27.863 に答える