【问题标题】:Referencing lua table/object after script has been run脚本运行后引用 lua 表/对象
【发布时间】:2020-02-09 14:36:56
【问题描述】:

我正在用 Lua 设计一个与 C++ 绑定的 GUI 系统。我不会在这里赘述不必要的细节,但本质上创建表单的 lua 脚本看起来是这样的:

local objectTwo = Gui:newObject{
    position = {10,10},
    size = {100,100},
}

local objectOne = Gui:newObject{
    position = {10,10},
    size = {100,100},
    handleOnClick = function(x, y, button)
        objectTwo:setProperties{
            hidden = false
        }
    end
}

本质上是 newObject 将表传递给 C++,handleOnClick 变成了一个自定义的 C++ 函数类。单击该对象时,它会调用该函数类并在 Lua 中对其进行评估。

然而,Lua 中不再存在 objectTwo,因为脚本已经运行,所以它尝试在 nil 上调用 setProperties 并崩溃。

我的问题是,如何确保在 handleOnClick 中仍然可以引用 objectTwo?我不想把它放在全局注册表或类似的地方,以避免污染命名空间。

我可以用闭包做些什么吗?

【问题讨论】:

    标签: c++ user-interface lua scripting


    【解决方案1】:

    在构造objectOne 时,local objectTwo 变量尚未在作用域内,因此 Lua 假定从从未定义的全局变量 objectTwo 读取,因此在读取时返回 nil

    至少将local objectTwo 声明移到将引用它的代码之前。您不必在此处定义对象,可以稍后执行分配。但是变量声明必须在要访问它的代码之前。

    还要注意数据/代码的所有权。您说您“将其转换为自定义 C++ 类”而没有额外的细节。您应该知道,您必须将回调函数的 Lua 值存储在某处。无论是注册表,还是某个类拥有的表,但仍存储在 Lua 可访问的某个位置,因此回调函数不会在稍后的某个时刻被垃圾收集。

    【讨论】:

    • 啊,是的,我写错了。我已经对其进行了编辑以反映 objectTwo 确实在 objectOne 之前声明...似乎 objectTwo 仍然以某种方式超出范围。使用注册表将对象转换为 C++。在 C++ 代码破坏引用 lua 对象的 C++ 对象之前,我确保它们不会被垃圾回收。
    • @KingCoyote objectTwo 在收集到 handleOnClick 中的函数之前无法进行 GC。 objectTwo 在回调的词法闭包中。你在某处存储objectOne 吗?它是脚本块的本地,如果它没有存储在其他地方,它将被 gc'ed,并且您的 c++ 析构函数将清理其他所有内容(如果正确完成),包括回调函数,因此 objectTwo 也将被清理。
    • objectTwo 和 objectOne 都作为 ref 存储在注册表中,属于两个单独的 c++ 对象。回调函数引用也存储在同一个 c++ 对象中,该对象包含对 objectOne 的引用。
    • @KingCoyote Final C++ 对象在注册表中。 Gui:newObject 的输入参数呢?那些有参数的表,你如何处理其中的数据?回调是一个 Lua 对象,而不仅仅是指向某些代码的指针。它必须保存在 Lua 中 - 在注册表中,或者嵌套在存储在注册表中的对象拥有的表中。
    • 是的,C++ 中的函数 Gui:newObject 获取输入表并引用它,并将其存储在 C++ 中。 newObject 将同一张表返回到 lua 中。本质上,C++ 对象包含对传递给 newObject 的表的引用,并且该表也由函数返回到 lua 中,因此它可以在其他地方使用。整个表格,包括大小、位置和 handleOnClick 函数,都被引用并存储在 C++ 中。
    猜你喜欢
    • 2015-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-19
    • 2015-08-30
    • 2014-09-27
    • 2019-07-25
    • 2018-08-05
    相关资源
    最近更新 更多