2

在 Lua 5.2 手册中,我们可以找到以下文本

创建 C 函数时,可以将一些值与其关联,从而创建 C 闭包(参见 lua_pushcclosure);这些值被称为 upvalues 并且在函数被调用时可以访问。

每当调用 C 函数时,它的上值都位于特定的伪索引处。这些伪索引由宏 lua_upvalueindex 生成。与函数关联的第一个值位于 lua_upvalueindex(1) 位置,依此类推。任何对 lua_upvalueindex(n) 的访问,其中 n 大于当前函数的上值数(但不大于 256),都会产生一个可接受的(但无效的)索引。

因此,我创建了一个与使用“new”创建的对象指针关联的回调函数。

lua_pushstring(L,"myCallbackFunc");
Foo* ideleg = new Foo()
lua_pushlightuserdata (L, (Foo*)ideleg);
lua_pushcclosure(L, LuaCall<Tr,C,Args...>::LuaCallback,1);
lua_settable(L,-3);

所有的机制都运行得很好……但是现在是清理的时候了,当我取消注册回调函数或退出程序时,我无法取回指针,因此我可以删除它。

我确实使用以下代码段找到了表条目:

lua_pushnil(L);
while (lua_next(L, -2) != 0)
{
    if (lua_isstring(L, -2) && lua_tostring(L,-2) == "myCallBackFunc" ) 
    {
        // get the pointer back and delete it!
    }
}

(我可以使用lua_getfield(L, -1, "myCallBackFunc");吗?)

但是我无法在函数外部获得与 cclosure 关联的上LuaCall<Tr,C,Args...>::LuaCallback()值(实际上在这个 close 函数内部我可以简单地使用lua_upvalueindex(1),但在这种情况下我在 close 函数之外......)

有没有办法获得这个值,这样我就可以在不再需要指针时删除它?


编辑:我确实找到了应该做我需要的lua_getupvalue函数,但目前我不知道如何获取 cclosure 堆栈索引。所以它仍然不起作用。

4

1 回答 1

4

是的,你可以在 Lua 中做到这一点。但我强烈建议不要这样做。

如果您可以访问该回调,如果它在 Lua 堆栈上,那么完全有可能某些 Lua 代码也可以访问它。这意味着即使你认为它会被销毁,但实际上直到 Lua 完成它才会被销毁。破坏你的闭包会使其进入非工作状态。然而,因为 Lua 可能仍然可以访问它,所以在你销毁它的 upvalue之后,可能会调用闭包。

坏事接踵而至。

最好将指针放入完整的用户数据并使用元方法将元表附加到它__gc以进行清理。这样,您可以确定它在真正不再使用时会被清理干净。

但是,如果您坚持按自己的方式进行操作,则始终可以使用lua_getupvalue.

于 2012-04-30T03:20:58.000 回答