Когда разрешено вызывать lua_gc в C++ при использовании lua_newuserdata

Приведенный ниже пример просто демонстрирует проблему/вопрос; на самом деле у меня есть функции, создающие и возвращающие множество различных объектов пользовательских данных, и между некоторыми из них я могу вызвать сборщик мусора Lua.

Кроме того, я использую Lua версии 5.3.3, работающую как в Windows, так и в Linux. Обработка ошибок не показана для простоты.

У меня есть класс С++, доступный для 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()

person Torben T Nielsen    schedule 07.08.2017    source источник


Ответы (1)


lua_setmetatable не удаляет объект из стека, поэтому существует ссылка на ваш объект пользовательских данных. Так что Lua его не соберет.

person moteus    schedule 07.08.2017
comment
Спасибо, вы должны быть правы. Ссылка должна находиться в стеке до тех пор, пока она не будет передана в Lua-переменную foo. - person Torben T Nielsen; 08.08.2017