问题
好的,让我们来看看这个函数和堆栈。
luaL_newmetatable(L, libname);
好的,堆栈现在包含来自元表注册表的表:
-1: table<libname>{possibly empty}
下一个:
lua_newtable(L);
堆栈现在包含:
-1: table<new>{empty}
-2: table<libname>{possibly empty}
下一个:
luaL_setfuncs(L,l,0);
不改变堆栈。但它确实在表中设置了一堆函数。
-1: table<new>{bunch of functions}
-2: table<libname>{possibly empty}
下一个:
lua_pushvalue(L,-1);
这会复制堆栈顶部的值。那是我们的表,有一堆函数:
-1: table<new>{bunch of functions}
-2: table<new>{bunch of functions}
-3: table<libname>{possibly empty}
下一个:
if(sublibname != NULL)
{
lua_newtable(L);
这会在堆栈上创建一个空的新表:
-1: table<new2>
-2: table<new>{bunch of functions}
-3: table<new>{bunch of functions}
-4: table<libname>{possibly empty}
下一个:
lua_setfield(L, -2, sublibname);
如文档中所述,此函数将值设置到给定表键名的表中。该值是堆栈顶部的值,但它放入的表是索引。
所以你只是这样做了:
-1: table<new>{bunch of functions, sublibname=table<new2>}
-2: table<new>{bunch of functions, sublibname=table<new2>}
-3: table<libname>{possibly empty}
我很确定这不是你想要的。当我们继续时,我将讨论如何解决这个问题。
下一个:
}
lua_setglobal(L, libname);
这将获取堆栈顶部并将其粘贴在全局表中,将其从堆栈顶部弹出。
所以堆栈现在看起来像这样:
-1: table<new>{bunch of functions, sublibname=table<new2>{empty}}
-2: table<libname>{possibly empty}
全局表现在有:
_G[libname] = table<new>{bunch of functions, sublibname=table<new2>{empty}}
因此,您不仅使堆栈不平衡(推送多于弹出),而且您没有得到您真正想要的东西。另外,注册表中的元表包含……什么都没有。
解决方案
所以让我们解决这个问题。让我们正确地做到这一点。
你试图做的几乎所有事情都是错误的。首先,做子表的唯一原因是这样的代码可以工作:
myregister(execContext, "dog", "beagle", fidofuncModule);
myregister(execContext, "dog", "dane", danefuncModule);
这样,您可以调用dog.beagle
和dog.dane
。好吧,要做到这一点,myregister
必须检查全局表以查看是否已经有一个dog
表。如果有,它需要在其中存储它的东西,如果没有,它需要创建它。所以你的整个算法有点坏了。
另外,大概你想要dog.beagle
并且dog.dane
两者都有自己的fetch
功能。好吧,注册表只有一个地方可以放一张dog
桌子,所以如果你只libname
用你的luaL_newmetatable
电话,他们会在彼此的桌子上跺脚。
这是我将如何解决它。我不知道这是否适用于您正在做的事情,但这就是我要做的。
首先,忘记整个newmetatable
废话;我们总是根据新表格工作。因此,我们将创建内部表并在其上设置函数:
lua_newtable(L);
luaL_setfuncs(L,l,0);
所以堆栈看起来像:
-1: table<new>{bunch of functions}
下一步,如果我们没有子库名称,那么我们应该直接将其设置到全局变量下libname
并返回:
if(!sublibname)
{
lua_setglobal(L, libname);
return;
}
这将从堆栈中弹出一个值并将其设置在该位置。
由于我们确实有一个子库名称,因此我们需要将此表存储在主表中。如果 中已经有一个表_G[libname]
,那么我们就得到那个表。否则,我们创建一个新表并将其粘贴到_G[libname]
.
lua_getglobal(L, libname);
if(lua_isnil(L, -1))
{
/*No table. Must create it and put it into the global*/
lua_newtable(L);
lua_pushvalue(L, -1); /*duplicate it on the stack*/
lua_setglobal(L, libname); /*pushes duplicate*/
}
此时,我们的堆栈包含:
-1: table<libname>{possibly empty}
-2: table<new>{bunch of functions}
然后,我们将创建的表粘贴到该表中,sublibname
用作字段:
lua_pushvalue(L, -2); /*duplicates our created table*/
lua_setfield(L, -2, sublibname);
现在堆栈包含:
-1: table<libname>{stuff, sublibname=table<new>{bunch of functions}}
-2: table<new>{bunch of functions}
由于表已经在全局表中(我们要么从那里得到它,要么在我们创建它时将它存储在那里),我们就完成了。所以清理堆栈:
lua_pop(L, 2); /*balance the stack. Remove our junk from it*/