Приведенный ниже пример просто для демонстрации проблемы / вопроса; на самом деле у меня есть функции создания
и возвращая много разных объектов userdata, и между некоторыми из них я могу захотеть вызвать сборщик мусора Lua.
Кроме того, я использую Lua версии 5.3.3, работающую как в Windows, так и в Linux. Обработка ошибок не показана для простоты.
У меня есть класс C ++, доступный Lua через стандартные пользовательские данные, как описано, например, в. «Программирование в Lua» Роберто Иерусалимского.
Моя проблема в том, что я не уверен, когда у Lua есть ссылка на мой объект, поэтому когда мне разрешено вызывать
сборщик мусора через C ++ функцию lua_gc?
У меня есть например стандартный класс Foo C ++ с конструктором и деструктором. И определил метатабельный «FOO» с функцией входа __gc, называемой ReleaseFoo, как также показано.
Я создаю экземпляр в Lua через следующий код C ++:
static int NewFoo(lua_State* L)
{
Foo** foo;
foo = (Foo**) lua_newuserdata(L, sizeof(Foo**));
*foo = new Foo();
luaL_getmetatable(L, "FOO");
lua_setmetatable(L, -2);
// QUESTION: Can I call lua_gc(L, LUA_GCCOLLECT, 0) here without
// risking my user data object being garbage collected.
// As I see it, Lua does not yet have a reference
// to my user data object.
return 1;
}
static int ReleaseFoo(lua_State* L)
{
Foo* foo = *(Foo**)lua_touserdata(L,1);
if (foo)
{
delete foo;
foo = NULL;
}
return 0;
}
В Lua его использование будет выглядеть следующим образом (поэтому только после возврата функции C ++ NewFoo (L) ссылка будет установлена, но я могу вызвать сборщик мусора, как показано?):
LUA> foo = NewFoo()
lua_setmetatable
не удаляет объект из стека, поэтому существует ссылка на ваш объект пользовательских данных. Так что Луа не соберет его.
Других решений пока нет …