因为我的userdata对象引用了自己,所以我需要删除和 nil一个变量才能使垃圾收集器工作。
Lua代码:
obj = object:new()
--
-- Some time later
obj:delete() -- Removes the self reference
obj = nil -- Ready for collection
C代码:
typedef struct {
int self; // Reference to the object
int callback; // Reference to a Lua function
// Other members and function references removed
} Object;
// Called from Lua to create a new object
static int object_new( 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 by Lua to delete an object
static int object_delete( lua_State *L ) {
Object *obj = lua_touserdata( L, 1 );
// Remove the objects self reference
luaL_unref( L, LUA_REGISTRYINDEX, obj->self );
return 0;
}
// Called from Lua to set a callback function
static int object_set_callback( lua_State *L ) {
Object *obj = lua_touserdata( L, 1 );
// Unref an existing callbacks
if ( obj->callback != 0 ) {
luaL_unref( L, LUA_REGISTRYINDEX, obj->callback );
obj->callback = 0;
}
// Set the new callback - function is on top of the stack
obj->callback = luaL_ref( L, LUA_REGISTRYINDEX );
}
// Called from C to call a Lua function for the obj
static void do_callback( Object *obj ) {
// Push the Lua function onto the stack
lua_rawgeti( L, LUA_REGISTRYINDEX, obj->callback );
// Push the userdata onto the stack
lua_rawgeti( L, LUA_REGISTRYINDEX, obj->self );
// Call the function
lua_call( L, 1, 0 );
}
有没有办法在Lua中将对象设置为nil,并自动调用delete()方法?或者,删除方法可以为所有引用该对象的变量吗?自我引用可以变得“弱”吗?
编辑1:我已经包含了代码来说明对象引用自身的原因;看到do_callback函数。每个对象都是树状结构的一部分,大部分处理在C中完成,但用户可以设置在某些条件下调用的自定义Lua函数。
编辑2:另一种可能的解决方案浮现在脑海中;而不是每个obj保持对自身的引用,当我需要将其地址作为键传递给Lua时,我可以在全局索引中查找对象吗?
答案 0 :(得分:1)
您可以尝试在注册表中创建一个弱表并在那里存储您的引用,这样将对象的所有引用设置为nil应该使它可用于gc。