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

时间:2022-03-31 09:42:45

In the following code, object of type foo is created with a call to foo_new() and an external-pointer to the object is returned to R. Subsequent computations are performed by passing ptr_foo. The object is eventually freed with an explicit call to foo_free(foo *X). All computations are performed by libfoo.

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

Does the fact that ptr_foo was created mean that all other dynamically allocated fields within the foo object are automatically protected? Or, is it possible that fields such as "bar" may be swept away by the garbage collector?

创建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);
} 

Thanks,

谢谢,

RT

RT

2 个解决方案

#1


3  

It looks like your foo object is your own creation (not and SEXP). If so, it has nothing to do with R and is NOT garbage collected and therefore does not need to be/can't be protected. No one will look at it or its fields but you.

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

The bar object you put in it is also your own creation and not an R object (an SEXP) I assume. If it IS an SEXP or points to data within an SEXP then that data needs to be protected. A safer/easier way would then be to make a copy of the data in the SEXP.

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

When the ptr_foo object is no longer used by R and garbage collected, your ptr_foo_finalize function will be called to remove your foo object (and the bar part).

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

#2


1  

For starters, you are not supposed to use calloc() or malloc() for R objects, the "Writing R Extensions" manual is pretty clear on that.

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

Second, each allocation would get its own PROTECT all.

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

Third, external pointer objects are R representations of something created elsewhere (for a canonical example , see the RODBC package and its implementation of DB interface). I don't think you're supposed to create external pointer objects from within.

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

#1


3  

It looks like your foo object is your own creation (not and SEXP). If so, it has nothing to do with R and is NOT garbage collected and therefore does not need to be/can't be protected. No one will look at it or its fields but you.

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

The bar object you put in it is also your own creation and not an R object (an SEXP) I assume. If it IS an SEXP or points to data within an SEXP then that data needs to be protected. A safer/easier way would then be to make a copy of the data in the SEXP.

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

When the ptr_foo object is no longer used by R and garbage collected, your ptr_foo_finalize function will be called to remove your foo object (and the bar part).

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

#2


1  

For starters, you are not supposed to use calloc() or malloc() for R objects, the "Writing R Extensions" manual is pretty clear on that.

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

Second, each allocation would get its own PROTECT all.

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

Third, external pointer objects are R representations of something created elsewhere (for a canonical example , see the RODBC package and its implementation of DB interface). I don't think you're supposed to create external pointer objects from within.

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