创建匿名用户数据变量

时间:2018-10-22 07:19:26

标签: lua anonymous-objects

我正在使用lua C api来运行与本机clase交互的脚本。我利用Qt的MOC来获取运行时类型信息。到目前为止,我已经实现了我希望lua能够与之交谈的所有类的创建,删除和索引。

这是我现在可以做的示例脚本:

myObject = MyClass.new()  --creates new userdata
otherObject = OtherClass.new()  --creates new userdata

myObject:functionForOthers(otherObject)  --method that takes userdata as argument

在该脚本中,otherObject被创建并保留在堆栈中。然后,它通过functionForOthers()传递,该OtherClass对象接受otherObject个对象。

但是,如果我不希望将myObject = MyClass.new() myObject:functionForOthers(OtherClass.new()) 放在堆栈中怎么办?如果我希望它成为仅在函数调用范围内存在的匿名变量,该怎么办?

OtherObject

这仍然有效,但是创建了new实例,但是从不将其分配给变量,直到作用域结束,它才在堆栈上不可访问。这不会引起任何直接的问题,但是会困扰我的内存效率方面。

我有很多处理这些操作后端的本机代码,但是其基本要点是MyClass是全局表OtherClasslua_newuserdata()的一个字段,指向本机CreateObject函数。在调用functionForOthers()

之后,从那里创建该类的实例并将其存储在用户数据中

__index调用利用了指向本机IndexObject函数的OtherClass元方法,该函数调用该方法(如果存在)。

实现匿名用户数据变量的基本方法是什么?我仍然希望这两个脚本都是有效的方法,我只想一种方法来将第二个脚本的using UnityEngine; using UnityEngine.UI; [RequireComponent(typeof(Button))] [DisallowMultipleComponent] public class HintsController : MonoBehaviour { private Image _image; private Text _text; private float _originalAlpha; // optional to control if Hints should be enabled on starting the App public bool enableAtStart; private void Awake() { // GetComponentInChildren finds the component on this object or any // child of this object recursively // (true) : make sure you also find the components if this or the child objects // are currently disabled // On this way you don't even have to rely on that the Image is on the // Button GameObject or below in the hierachy _image = GetComponentInChildren<Image>(true); _text = GetComponentInChildren<Text>(true); if(_image) { _originalAlpha = _image.color.a; } // optional to controll if Hints should be enabled on starting the App ShowHints(enableAtStart); } public void ShowHints(bool isVisible) { // Skip if no Image found if (_image) { var color = _image.color; color.a = isVisible ? _originalAlpha : 0; _image.color = color; } // Skip if no Text found if (_text) { _text.enabled = isVisible; } } } 对象保留在作用域内,直到函数调用完成为止。

1 个答案:

答案 0 :(得分:1)

感觉您对Lua的某些部分有误解。

将某些对象作为参数传递给函数不会将该对象“保留”在堆栈中。堆栈仅存储对对象的引用。对同一对象的另一个引用存储在otherObject变量中。当您将变量作为参数传递给functionForOthers()时,会将引用按值复制到堆栈中,并且一旦调用函数返回控制,该引用就会从堆栈中弹出。

对象本身存储在Lua堆上。当垃圾收集器发现该对象没有引用时,它将最终被销毁/收集。该对象不会在作用域末尾销毁,只会丢失引用。何时真正删除对象取决于垃圾收集器。

如果您担心内存不足,可以定期调用collectgarbage()。但这可能会使您的程序停顿一段时间,因此请选择合适的时机。否则,您可以完全忽略它,只需确保您没有收集对某些长期存在的对象(全局变量,注册表或您自己的字典/缓存)的引用。除非您无意间创建了非常深或无限的递归调用,否则堆栈上的引用会快速删除。无法到达的对象将被自动删除,这就是标记清除垃圾收集器的工作方式。