2010-08-26 27 views
5

Supponendo la seguente situazione:Lua: garbage collection + datiutente

typedef struct rgb_t {float r,g,b} rbg_t; 

// a function for allocating the rgb struct 
rgb_t* rgb(r,g,b) { 
rgb_t* c = malloc(sizeof(rgb_t)); 
c->r=r; 
c->g=g; 
c->b=b; 
return c; 
} 

// expose rgb creation to lua 
int L_rgb (lua_State* L) { 
rgb_t** ud = (rgb_t **) lua_newuserdata(L, sizeof(rgb_t *)); 
*ud = rgb(lua_tonumber(L,1),lua_tonumber(L,2),lua_tonumber(L,3)); 
return 1; 
} 

Quando la funzione L_rgb viene chiamata da Lua due assegnazioni accada. Lua alloca nuovi dati utente e la funzione di costruzione rgb alloca per la struct. Cosa succede alla variabile userdata quando la variabile esce dallo scope in Lua? Se è raccolta la spazzatura, cosa succede all'assegnazione della struttura?

risposta

12

Hai due approcci a questa situazione, ed entrambi potrebbero applicarsi al tuo caso specifico. Altri casi ti spingono più forte a sceglierne uno rispetto all'altro.

  1. Si può fare come si fa in vostro campione, e utilizzare malloc() per ottenere il vostro blocco di dati privati, e memorizzare un puntatore ad esso in un userdata pieno. Se si esegue questa operazione, è necessario impostare una metatable sui dati utente e utilizzare il metametodo __gc per liberare il blocco assegnato quando i dati utente vengono raccolti.

  2. È possibile utilizzare lo userdata stesso come allocazione per il blocco di dati privato, chiamando lua_newuserdata() al posto di malloc(). In questo caso non è necessario disporre di un metametodo __gc poiché Lua gestirà direttamente la durata dell'assegnazione. Potresti ancora voler avere una metatable in modo che tu possa usare la sua voce __index per creare l'aspetto dei membri chiamati r, g e b che recuperano i loro valori dalla tua struct.

In entrambi i casi, è necessario pensare alla gestione degli errori.

+2

alleggerirà le allocazioni di tracciamento: sugli errori Lua e sui riavvolgitori, il GC di Lua traccerà e rilascerà i blocchi di codice come appropriato. – u0b34a0f6ae

+0

C'è una modifica che puoi aiutare qui: http://stackoverflow.com/questions/41080633/can-i-load-additional-functions-in-base-open-without-breaking-lua-state? – displayname

2

aggiungere un metatable ai propri dati utente e impostare la chiave __gc per la funzione deallocation. Vedi the docs

+0

Qualsiasi idea del problema è qui: http://stackoverflow.com/questions/41080633/can-i-load-additional-functions-in-base-open-without-breaking-lua-state? Il metodo n. 2 – displayname