2011-07-20 11 views
5

次のコードでは、foo_new()の呼び出しでfoo型のオブジェクトが作成され、オブジェクトへの外部ポインタがR ptr_fooを渡すことによって後続の計算が実行されます。オブジェクトはfoo_free(foo * X)を明示的に呼び出すと、最終的に解放されます。すべての計算はlibfooによって実行されます。R .call()インタフェースとEXTPTRSXP:外部で割り当てられたオブジェクトによる保護/保護解除の理解

ptr_fooが作成されたという事実は、fooオブジェクト内の他の動的に割り当てられたフィールドがすべて自動的に保護されることを意味しますか?または、 "bar"のようなフィールドがガベージコレクタによって掃除される可能性はありますか?

SEXP foo_new (SEXP n) { 
    SEXP ptr_foo; 
    foo *X = (foo*) foo_new(1, sizeof(foo)); 
    //foo is protected from garbage collection 
    assert(X); 
    X->bar = (int*) foo_add_bar(INTEGER_VALUE(n)); 
    //Is bar protected from garbage collection? 
    assert(X->bar); 
    PROTECT(ptr_foo = R_MakeExternalPtr(X, install("extptr_foo"), R_NilValue)); 
    R_RegisterCFinalizerEx(ptr_foo, ptr_foo_finalize, 1); 
    UNPROTECT(1); 
    return (ptr_foo); 
} 

おかげで、

RT手始めに

答えて

3

あなたのfooオブジェクトはあなた自身の作成物です(SEXPではなく)。そうであれば、それはRとは無関係で、ガーベジコレクションされないため、保護する必要はなく/保護することもできません。誰もそれを見ないでしょう。

あなたが置いたバーオブジェクトも自分の作成であり、私が想定しているRオブジェクト(SEXP)ではありません。それがSEXPであるかSEXP内のデータを指している場合は、そのデータを保護する必要があります。より安全で簡単な方法は、SEXPでデータのコピーを作成することです。

ptr_fooオブジェクトがRで使用されなくなってガベージコレクトされると、ptr_foo_finalize関数が呼び出されてfooオブジェクト(およびバー部分)が削除されます。

+0

ありがとうTommy。それが私が望んでいたものです。あなたが指摘しているように、Rとlibfooの間のすべてのデータ交換は、SEXPをコピーして出し入れすることによって行われます。ライブラリによって割り当てられたすべてのオブジェクトは、foo_free()呼び出しによって解放されます。 – user151410

1

は、あなたがRオブジェクトのcalloc()またはmalloc()を使用することになっていない、 "ライティングR拡張機能" マニュアルは、その上かなり明確です。

第2に、各割り当ては、それ自身のPROTECT allを得る。

第3に、外部ポインタオブジェクトは、他の場所で作成されたもののR表現です(正規の例については、RODBCパッケージとそのDBインタフェースの実装を参照してください)。私はあなたが内部から外部ポインタオブジェクトを作成するはずだとは思わない。

+0

ありがとうDirk、私は私の元のコードを編集しました。例を単純にするために 'calloc()'を使いました。 'foo'と' bar'を含む作成、破壊、計算は 'libfoo'の関数呼び出しによって行われます。 RODBCパッケージへのポインタをありがとう。 – user151410

関連する問題