2012-06-15 3 views
11

Avere qualche problema con la garbage collection di R, quando si passano oggetti in C++.come inibire la garbage collection di R quando si passano oggetti in C/C++?

Abbiamo il seguente scenario:

  1. ci consente di creare una funzione anonima in R, e passarlo al codice C++ (via .Call())
  2. il codice C++ memorizza l'oggetto funzione R per un uso successivo (come un tipo SEXP) e restituisce
  3. seguito, qualche altro codice C++ invoca detta funzione dell'oggetto R utilizzando R_tryEval()

Tra passaggi 2 e 3, l'oggetto della funzione R sembra recuperare la garbage collection da R. Questo porta a un arresto anomalo perché R_tryEval() tenta di eseguire qualcosa che non rappresenta più un oggetto funzione R valido. Questo è giusto, in quanto non abbiamo fatto nulla per dire R che l'oggetto funzione è ancora in uso ...

Con questo in mente:

  • c'è un modo, dal codice C++, per segna l'oggetto della funzione R come in uso (in modo tale da non ottenere gc'd)?
  • oppure esiste un modo sicuro per duplicare l'oggetto funzione R, all'interno del codice C++, e smaltirlo manualmente dopo aver invocato R_tryEval()?

(Per quanto ho capito, le macro PROTECT()/UNPROTECT() non sono un'opzione qui perché coloro che si suppone per bilanciare all'interno della stessa portata. Come in, non possiamo chiamare PROTECT() quando la funzione è prima passato per C++ e poi chiamare UNPROTECT() dopo che è stato eseguito.)

+0

Come stai "memorizzando" l'oggetto? Penserei (senza pensarci davvero) si può usare un puntatore esterno. In caso contrario, potresti essere in grado di mantenerlo in vita in R da qualche parte e utilizzare findVar per richiamarlo quando necessario. –

+0

@Jeff - grazie. Quello che hai descritto è molto vicino alla soluzione che abbiamo escogitato: aggiungere gli oggetti funzione a un elenco, sul lato R, prima di passarli a C++. (Siamo felici di continuare a farlo, tra l'altro ... volevo solo assicurarmi che non ci fosse alcuna funzione "ufficiale" che dovremmo chiamare per contrassegnare l'oggetto come non-gc.) – qethanm

+1

Per quanto riguarda gli hack vai, questo può prendere la torta. Vedi la risposta di Martin per una soluzione adeguata anche se non usi Rcpp. –

risposta

3

Penso che stai cercando

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

nell'intestazione R_internals.h.

+0

... e se hai usato Rcpp questo sarebbe applicato automaticamente agli oggetti. –

+0

Mille grazie - questo è proprio quello che cercavo. Caso chiuso. – qethanm