3

下面的例子只是为了演示问题/问题;实际上,我有创建和返回许多不同 userdata 对象的函数,其中一些我可能想调用 Lua 垃圾收集器。

另外,我使用的是 Lua 版本 5.3.3,在 Windows 和 Linux 上都运行。为简单起见,未显示错误处理。

我有一个通过标准用户数据向 Lua 公开的 C++ 类,如 Roberto Ierusalimschy 的“在 Lua 中编程”中所述。我的问题是我不确定 Lua 何时确实引用了我的对象,那么何时允许我通过 C++ lua_gc 函数调用垃圾收集器?

例如,我有带有构造函数和析构函数的标准 Foo C++ 类。并使用名为 ReleaseFoo 的 __gc 入口函数定义了一个元表“FOO”,如图所示。

我通过以下 C++ 代码在 Lua 中创建一个实例:

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()
4

1 回答 1

3

lua_setmetatable不会从堆栈中删除对象,因此存在对您的 userdata 对象的引用。所以Lua不会收集它。

于 2017-08-07T13:43:16.753 回答