Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R.call()接口和EXTPTRSXP:了解外部分配对象的保护/取消保护_C_R_Memory Management_Externalinterface - Fatal编程技术网

R.call()接口和EXTPTRSXP:了解外部分配对象的保护/取消保护

R.call()接口和EXTPTRSXP:了解外部分配对象的保护/取消保护,c,r,memory-management,externalinterface,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_ne

在下面的代码中,通过调用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

对于初学者,您不应该对R对象使用
calloc()
malloc()
,“编写R扩展”手册对此非常清楚

第二,每个分配都有自己的保护所有人


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

看起来您的foo对象是您自己创建的(而不是SEXP)。如果是这样的话,它与R无关,并且不是垃圾收集的,因此不需要/无法进行保护。除了你,没有人会看它或它的领域

你放在里面的bar对象也是你自己创建的,而不是我假设的R对象(SEXP)。如果是SEXP或指向SEXP中的数据,则需要保护该数据。一种更安全/更简单的方法是在SEXP中复制数据


当ptr\u foo对象不再被R使用并被垃圾回收时,将调用ptr\u foo\u finalize函数来删除foo对象(以及条形图部分)。

谢谢Dirk,我编辑了我的原始代码。我使用
calloc()
只是为了使示例简单。涉及
foo
bar
的创建、销毁和计算通过调用
libfoo
中的函数来执行。谢谢你提供RODBC包的指针。谢谢汤米。这就是我所希望的。正如您所指出的,R和libfoo之间的所有数据交换都是通过复制SEXPs来实现的。库分配的所有对象都通过foo_free()调用释放。