Original Post
Hi all, I'll start by saying this is probably a trivial concern, but it's been bothering me all afternoon. The collective wisdom here has never failed me before! My Lua userdata objects contain a reference to themselves so C functions can pass the objects to Lua callback functions: Each object shares a metatable for various methods, and a __gc callback for the garbage collector; nothing unusual there. The main loop in C runs, calls any Lua callbacks required by the objects and all works well. My grief is the deletion of the object when it is no longer required: In Lua: I have to call both 'obj:delete()' and 'obj = nil' for the GC to release the resources. Is there a way for the delete() function to nil any Lua variables that reference the userdata object? Some other solution would be most welcome!
// Code stripped down to the bare essentials!
typedef struct {
int self; // Reference to the object
int callback; // Reference to a function
} Object;
// Called from Lua to create a new object
static int new_object( lua_State *L ) {
Object *obj = lua_newuserdata( L, sizeof( Object ) );
// Create the 'self' reference, userdata is on the stack top
obj->self = luaL_ref( L, LUA_REGISTRYINDEX );
// Put the userdata back on the stack before returning
lua_rawgeti( L, LUA_REGISTRYINDEX, obj->self );
// The object pointer is also stored outside of Lua for processing in C
return 1;
}
// Called from Lua to set a callback function for an object
static int set_callback( lua_State *L ) {
Object *obj = lua_touserdata( L, 1 );
// Unref any previous callback functions
if ( obj->callback != 0 ) luaL_unref( L, LUA_REGISTRYINDEX, obj->callback );
// Reference the new callback
obj->callback = luaL_ref( L, LUA_REGISTRYINDEX );
return 0;
}
// Called by Lua to delete an object
static int obj_delete( lua_State *L ) {
Object *obj = lua_touserdata( L, 1 );
if ( obj->callback != 0 ) luaL_unref( L, LUA_REGISTRYINDEX, obj->callback );
// Remove the objects self reference
luaL_unref( L, LUA_REGISTRYINDEX, obj->self );
return 0;
}
// Called by the Lua garbage collector
static int gc_collect( lua_State *L ) {
// Do cleanup stuff
return 0;
}
// Called from C to call the Lua callback function for an object
static void do_callback( lua_State *L, Object *obj ) {
// Push the callback function onto the stack
lua_rawgeti( L, LUA_REGISTRYINDEX, obj->callback );
// Push the args onto the stack
lua_rawgeti( L, LUA_REGISTRYINDEX, obj->self );
// Call the function
lua_call( L, 1, 0 );
}
-- Setup
obj = Object:new()
obj:set_callback( some_lua_function )
-- Elsewhere, some time later
obj:delete() -- required to remove the self reference
obj = nil