R .call()接口和EXTPTRSXP:了解外部分配的对象的PROTECT / UNPROTECT

时间:2011-07-20 04:41:13

标签: c r memory-management externalinterface

在下面的代码中,通过调用foo_new()创建foo类型的对象,并将对象的外部指针返回给R.后续计算通过传递ptr_foo来执行。最终通过显式调用foo_free(foo * X)释放该对象。所有计算都由libfoo执行。

创建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

2 个答案:

答案 0 :(得分:3)

看起来你的foo对象是你自己的创造(不是和SEXP)。如果是这样,它与R无关,也不是垃圾收集,因此不需要/不能保护。除了你,没有人会看它或它的领域。

您放入的条形对象也是您自己的创建,而不是我假设的R对象(SEXP)。如果它是SEXP或指向SEXP内的数据,则需要保护该数据。然后,更安全/更简单的方法是在SEXP中复制数据。

当R不再使用ptr_foo对象并收集垃圾时,将调用ptr_foo_finalize函数来删除你的foo对象(以及条形部分)。

答案 1 :(得分:1)

对于初学者,你不应该对R对象使用calloc()malloc(),“Writing R Extensions”手册非常清楚。

其次,每个分配都将获得自己的PROTECT。

第三,外部指针对象是在别处创建的东西的R表示(对于规范示例,请参阅RODBC包及其DB接口的实现)。我不认为你应该从内部创建外部指针对象。