如何在Lua中将函数调用与中间返回对象链接在一起,而垃圾回收器不会立即破坏对象呢?

时间:2019-02-03 00:16:40

标签: lua

我在Lua中有如下代码:

mv.getLabelChildByNameSequence("confirm_btn|button|no_icon_txt").setVisible(false);

getLabelChildByNameSequence()返回一个userdata对象(在c端创建),然后setVisible()对该对象调用一个函数。问题是,它在大多数时间都有效,但是有时,垃圾收集器决定在创建之后,语句的第二部分发生之前立即销毁中间对象。

我发现这更成功:

local no_icon_txt = mv.getLabelChildByNameSequence("confirm_btn|button|no_icon_txt");
no_icon_txt.setVisible(false);

我怀疑使用显式local变量,引用计数按预期方式工作,并且直到局部变量超出范围才对对象进行垃圾回收。

相对于第二个示例,我更喜欢第一个示例-它更紧凑,更漂亮,并且更像您在c++这样的语言中看到的内容。我该如何实现?

顺便说一句,当崩溃发生时,尽管只是垃圾收集了数据,但它似乎确实试图将对setVisible()的调用解析为对象的旧内存地址。很好奇。

编辑:我要提到的是我使用LunaFive进行绑定(http://lua-users.org/wiki/LunaFive)。用户数据推送fn如下所示:

    static void push(lua_State * L, T* instance )
    {
        T **a = (T **) lua_newuserdata(L, sizeof(T *)); // Create userdata
        *a = instance;

        luaL_getmetatable(L, T::className);

        lua_setmetatable(L, -2);
    }

函数分派如下所示:

    static int function_dispatch(lua_State * L)
    {
        int i = (int) lua_tonumber(L, lua_upvalueindex(1));
        T** obj = static_cast < T ** >(lua_touserdata(L, lua_upvalueindex(2)));

        return ((*obj)->*(T::methods[i].func)) (L);
    }

getLabelChildByNameSequence()推送Label类的一个新实例(比方说),而setVisible()是该类的一个方法。

1 个答案:

答案 0 :(得分:0)

根据对我的问题的评论中的反馈,我所做的事情被删除了函数分派中的lua_upvalueindex()业务,而是要求将userdata作为函数回调的第一个参数。然后,我将点表示法切换为冒号表示法,并提供了隐式self。从那以后再也无法重现崩溃。

我仍然不明白为什么在函数调用之前没有正确地对upvalue进行计数。也许在对象创建中缺少一些东西。