2014-01-07 5 views
9

高速化のためにRcppを使用して関数を定義しようとしています。状況は次のようになります。パッケージBARのRパッケージFOOのC++コードを使用する最善の方法

  • 私は、多くのC++コード(自分のパッケージと現在はRcppを使用していません)を持つパッケージFOOを持っています。 foo_aとfoo_b。
  • 別のパッケージBAR(Rcppを使用)では、関数foo_aとfoo_bを呼び出す関数を定義しています(Rcpp属性を使用しています)。

どうすれば解決できますか?他の投稿を少し見て、私はFOOにヘッダファイルを組み込み、BARに属性を使用する方法をいくつか持っていますが、私はいくつかの点を逃しているようです。どのようにそれを行うためのヒント?

ベストラース

EDIT:コメントのおかげで、私はケビンUsheysのアプローチが好きで、それを実装しようとしました。しかし、いくつかのコーディングの後、私は実際にはFOOの関数ではなく、クラスとそのpublic関数が必要であることに気付きました。私はあなたがクラスのために提案したトリックをすることはできないと思います。私はクラスのソースファイルをBOOのsrcディレクトリに置いてしまいました(同じコードの2つのバージョンを持っているので、最良のアプローチではありません)。しかし、現時点では、このハックは私のために働く。

+1

は/計器に入れてパッケージFOOのインクルード(src/Makevarsに-I ../ inst/includeをセットし、パッケージBARにRcppDepends(FOO)を使用させる - コピーを1つだけ使用する、それを使用する2つのパッケージRcppXtsについて書いた内容を見る –

+0

ありがとうDirk。私はRcppXtsを見ていますが、クラスでも可能だとは思いませんでした。 – Relund

答えて

4

別のオプションは、ケースであなたは、パッケージFOORcppを導入する気にしない - Section 3.5 of Rcpp-attributesと一緒に従うと、次の操作を行います。「機能、あなたを含む.cppのソースファイルの先頭に

  1. 場所// [[Rcpp::interfaces(cpp)]]を他のパッケージに利用できるようにしたいとdは、エクスポートしたいこれらの関数の前で

  2. 場所// [[Rcpp::export]]

  3. その後、 // [[Rcpp::depends(FOO)]]を使用して、パッケージ BARで使用することができます inst/includeでファイルを生成する FOOのパッケージディレクトリ内
  4. コールcompileAttributes()

  5. パッケージFOOをインストールします。

あなたは、これが正しく設定されている場合、あなたはこのようなテンプレートを使用して関数を呼び出すことができるはずです(foo_aを想定すると、FOOからエクスポートされた関数です):

// [[Rcpp::depends(FOO)]] 

#include <Rcpp.h> 
#include <FOO.h> 
using namespace Rcpp; 

// [[Rcpp::export]] 
SEXP some_function() { 
    return FOO::foo_a(); 
} 
+0

これは実際には他の2つの答えと同じですが、より簡単に完了します:) –

8

私は、これらのオプションのいずれかをお勧めします:

foo_afoo_bは十分に簡単であれば、単にFOOのヘッダにinline機能として、それらを持っているとFOO/inst/include/FOO.hでこれらのヘッダを置きます。 BARcompileAttributes(またはおそらくload_all)を呼び出すと、Rcpp::depends(FOO)にこのファイルが含まれます。

それ以外の場合は、Rの登録モデルを使用して機能を登録することを検討してください。これはもう少し作業ですが、それは耐え難いことです。 Rエクステンションの記述には詳細があります。私はすべての登録ロジックをFOOに入れて、クライアントパッケージBARだけがそれを使用するようにすることをお勧めします。たとえば、FOOのヘッダーには、foo_aがあります。

#ifdef COMPILING_FOO 
inline int foo_a(int x, double y, const std::string& z){ 
    typedef int (*Fun)(int, double, const std::string&) ; 
    static Fun fun = (Fun)R_GetCCallable("FOO", "foo_a") ; 
    return fun(x,y,z) ; 
} 
#else 
// just declare it 
int foo_a(int x, double y, const std::string& z) ; 
#endif 

FOO/srcでいくつかの.cppファイル内foo_aの実際の定義:FOO/inst/include/FOO.hで次に

#define COMPILING_FOO 
#include <FOO.h> 

int foo_a(int x, double y, const std::string& z){ 
    // do stuff 
} 

、あなたが機能R_init_FOOR_RegisterCCallableを使用してfoo_aを登録する必要があります。

extern "C" void R_init_FOO(DllInfo* info){ 
    R_RegisterCCallable("FOO", "foo_a", (DL_FUNC)foo_a); 
} 
+0

もちろん、R_init_FOOです。私がどこからその例を得たのか。 –

2

RcppXtsパッケージdよく知られたxtsパッケージからの一連の機能のためのものです。

編集:ここにxtsのコードがあります。まず

、XTS ::のsrc/init.c、XTS ::研が//xtsApiを

R_RegisterCCallable("xts","do_is_ordered",(DL_FUNC) &do_is_ordered); 

セカンドのようなダースかそこらの宣言を経由して登録含まれません。hは、そのような私たちが

均等に我々はできるR.にそれを公開し
function("xtsIsOrdered", 
     &xtsIsOrdered, 
     List::create(Named("x"), 
         Named("increasing") = true, 
         Named("strictly") = true), 
     "Tests whether object is (strictly) (increasing) ordered"); 

として(Rcppモジュールを使用して)これを定義RcppXtsとしてクライアントパッケージに、例えば

SEXP attribute_hidden xtsIsOrdered(SEXP x, SEXP increasing, SEXP strictly) { 
    static SEXP(*fun)(SEXP,SEXP,SEXP) = NULL; 
    fun = (SEXP(*)(SEXP,SEXP,SEXP)) R_GetCCallable("xts","do_is_ordered"); 
    return fun(x, increasing, strictly); 
} 

サードでクライアントパッケージのヘッダーを提供しますC++コードからC関数xtsIsOrderedを呼び出してください。

私は関数が 'SEXP in、SEXP out'に従わなければならないという誤った以前のコメントを削除しました。

+0

"すべてがRを通して起こるので、関数は 'SEXP foo(SEXP a、SEXP b、...)スキームに適合しなければなりません。 –

+0

さらに優れています。このスキームがC++オブジェクトを交換するために使用されるどこかの実例がありますか? lme4とMatrixの基本例はIIRCではありません。 –

+0

Rcppは明白な例です。 –

関連する問題