在下面的代码中,通过调用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
答案 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接口的实现)。我不认为你应该从内部创建外部指针对象。