2012-06-15 10 views
11

Tiene problemas con la recolección de elementos no utilizados de R, al pasar objetos a C++.cómo inhibir la recolección de basura R al pasar objetos a C/C++?

tenemos el siguiente escenario:

  1. creamos una función anónima en R, y pasarlo a código C++ (a través de .Call())
  2. el código C++ almacena el objeto función R para su uso posterior (como se un tipo SEXP) y devuelve
  3. más adelante, algún otro código C++ invoca dicho objeto función R usando R_tryEval()

Entre los pasos 2 y 3, el objeto de la función R aparece para obtener el recolector de basura por R. Esto provoca un bloqueo porque R_tryEval() intenta ejecutar algo que ya no representa un objeto de función R válido. Eso es justo, ya que no hemos hecho nada para contar R que el objeto función está todavía en uso ...

Con esto en mente:

  • hay una manera, a partir del código C++, a marcar el objeto de la función R como en uso (de modo que no se obtenga gc'd)?
  • o existe una forma segura de duplicar el objeto de la función R, dentro del código C++, y deshacerse de él manualmente después de invocar R_tryEval()?

(Por lo que yo entiendo, los PROTECT()/UNPROTECT() macros no son una opción aquí porque aquellos se supone que equilibrar dentro del mismo ámbito. Como en, no podemos llamar PROTECT() cuando la función se pasa primero a C++ y luego llamar UNPROTECT() después de que haya sido ejecutado.)

+0

¿Cómo está 'almacenando' el objeto? Yo pensaría (sin pensar realmente) que puedes emplear un puntero externo. De lo contrario, quizás puedas simplemente mantenerlo vivo en R en alguna parte y usar findVar para recuperarlo cuando sea necesario. –

+0

@Jeff - gracias. Lo que ha descrito está muy cerca de la solución que ideamos: agregar los objetos de función a una lista, en el lado R, antes de pasarlos a C++. (Por cierto, estamos contentos de seguir haciendo esto ... solo queríamos asegurarnos de que no hay una función "oficial" a la que se suponga que llamemos para marcar el objeto como do-not-gc). – qethanm

+1

En cuanto a hacks ve, esto puede tomar el pastel. Consulte la respuesta de Martin para una solución adecuada, incluso si no utiliza Rcpp. –

Respuesta

3

Creo que estás buscando

/* preserve objects across GCs */ 
void R_PreserveObject(SEXP); 
void R_ReleaseObject(SEXP); 

en la cabecera R_internals.h.

+0

... y si usó Rcpp esto se aplicaría automágicamente a sus objetos. –

+0

Muchas gracias, esto es justo lo que estaba buscando. Caso cerrado. – qethanm

Cuestiones relacionadas