2011-07-20 11 views
5

En el siguiente código, objeto de tipo foo se crea con una llamada a foo_new() y un puntero externo al objeto se devuelve al R Los cálculos posteriores se realizan pasando ptr_foo. El objeto finalmente se libera con una llamada explícita a foo_free (foo * X). Todos los cálculos son realizados por libfoo.R .call() de interfaz y EXTPTRSXP: La comprensión de Protección/desprotección con objetos asignados externamente

El hecho de que ptr_foo fue creado significa que todos los otros campos asignados dinámicamente dentro del objeto foo están protegidos de forma automática? ¿O es posible que campos como "barra" puedan ser eliminados por el recolector de basura?

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

Gracias,

RT

Respuesta

3

parece que su objeto foo es su propia creación (no y SEXP). Si es así, no tiene nada que ver con R y NO es basura recolectada y por lo tanto no necesita ser/no puede ser protegida. Nadie lo mirará o sus campos excepto usted.

El objeto de barras que pone en él es también su propia creación y no un objeto R (un SEXP) que asumen. Si ES un SEXP o apunta a datos dentro de un SEXP, entonces esos datos deben ser protegidos. Una manera más segura/más fácil sería hacer una copia de los datos en el SEXP.

Cuando el objeto ptr_foo ya no se usa por R y basura recogida, su función ptr_foo_finalize serán llamados a quitar su objeto foo (y la parte bar).

+0

Gracias Tommy. Eso es lo que esperaba. Como indica, todo el intercambio de datos entre R y libfoo ocurre copiando SEXPs dentro y fuera. Todos los objetos asignados por la biblioteca son liberados por una llamada foo_free(). – user151410

1

Para empezar, no se supone que el uso calloc() o malloc() de objetos R, el manual "Escritura R Extensiones" es bastante claro al respecto.

segundo lugar, cada asignación obtendría su propio proteger a todos.

tercer lugar, los objetos externos son punteros R representaciones de algo creado en otro lugar (para un ejemplo canónico, consulte el paquete RODBC y su implementación de la interfaz DB). No creo que se suponga que debes crear objetos de puntero externos desde adentro.

+0

Gracias Dirk, edité mi código original. Usé 'calloc()' solo para mantener el ejemplo simple. La creación, destrucción y cálculos que involucran 'foo' y' bar' se realizan mediante llamadas a funciones en 'libfoo'. Gracias por el puntero al paquete RODBC. – user151410

Cuestiones relacionadas