2012-01-04 10 views
2

.Callの配列をC共有ライブラリの関数に戻し、その配列をRで使用するにはどうすればよいですか?例えば.CallからC共有ライブラリへの構造体の配列を返す方法

typedef struct{ 
    int thing1; 
    int thing2; 
    float thing3; 
    float thing4; 
    char thing5; 
    //... many more things of various simple types 
} MY_STRUCT; 

SEXP R_Calls_Me(SEXP args) { 

    // Do stuff with args... 

    // Create arrayOfMyStructs as what type?? 

    return arrayOfMyStructs; 
} 

どのようなタイプは、Rは、それを使用することができarrayOfMyStructsなのですか?

これは一般的なことですが、R拡張を記述するためのドキュメントではこれの例は見つかりません。

答えて

3

通常は、返すコンポーネントでリスト(ジェネリックベクター)を作成します。あなたのケースでは

SEXP res = PROTECT(allocVector(VECSXP, 5)); 
SET_VECTOR_ELT(res, 0, ScalarInteger(a.thing1)); 
SET_VECTOR_ELT(res, 1, ScalarInteger(a.thing2)); 
SET_VECTOR_ELT(res, 2, ScalarReal(a.thing3)); 
... 
UNPROTECT(1) 
return res; 

のようなものは、例えば、また、ベクターに名前を割り当てることが通例である。:

const char *names[5] = { "thing1", "thing2", "thing3", "thing4", "thing5" }; 
SEXP sNames = PROTECT(allocVector(STRSXP, 5)); 
for (int i = 0; i < 5; i++) SET_STRING_ELT(res, i, mkString(names[i])); 
setAttrib(res, R_NamesSymbol, sNames); 
UNPROTECT(1); 

注意何を記述していることない配列が、構造であること。通常、配列はベクトルとして渡す方がはるかに簡単です。

+0

最終的に私が望むのは、C関数への単一の呼び出しを使用してこれらの構造の任意の数を返すことができることです。あなたの例は、1つの構造体を返す方法を示しています。これを達成するためにベクトルのベクトルを単純に作成できますか? – cachance7

+0

これは便利なことです。あるいは、それらが同じであれば、配列(=ベクトル)を使うことができます。列が構造レコードであり、行が異なる構造であるデータフレームを考えます。 'SET_VECTOR_ELT(res、0、ScalarInteger(a.thing1))'の代わりに、 'SEXP t1 = allocVector(INTSXP、n);のようなものを置き換えます。 SET_VECTOR_ELT(res、0、t1); int * t1i = INTEGER(t1); (int i = 0; i

+0

私はあなたの2番目のアプローチがRで返されたデータをどのように使用するのかを最も理にかなっていると思います。ありがとうございました。 – cachance7

2

これを行う最も自然な方法は、おそらく外部ポインタを使用することです。 Rへのポインタを返すと、アプリケーションコードがそれを操作します。これを行う多数のパッケージ(例えば、XML、h5r)。

SEXP _h5R_make_ptr() { 
    h5_holder* holder = (h5_holder*) Calloc(1, h5_holder); 
    holder->id = 1; 
    holder->is_file = 0; 
    SEXP e_ptr = R_MakeExternalPtr(holder, R_NilValue, R_NilValue); 
    PROTECT(e_ptr); 
    R_RegisterCFinalizerEx(e_ptr, h5R_finalizer, TRUE); 
    UNPROTECT(1); 
    return e_ptr; 
} 
+0

Rでそれらを使用することはできません。外部ポインタは、Rにアクセスする方法がない不透明な構造体にのみ役立ちます(「後でRで使用できない」を参照)。 –

関連する問題