我正在使用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
是全局表OtherClass
和lua_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;
}
}
}
对象保留在作用域内,直到函数调用完成为止。
答案 0 :(得分:1)
感觉您对Lua的某些部分有误解。
将某些对象作为参数传递给函数不会将该对象“保留”在堆栈中。堆栈仅存储对对象的引用。对同一对象的另一个引用存储在otherObject
变量中。当您将变量作为参数传递给functionForOthers()
时,会将引用按值复制到堆栈中,并且一旦调用函数返回控制,该引用就会从堆栈中弹出。
对象本身存储在Lua堆上。当垃圾收集器发现该对象没有引用时,它将最终被销毁/收集。该对象不会在作用域末尾销毁,只会丢失引用。何时真正删除对象取决于垃圾收集器。
如果您担心内存不足,可以定期调用collectgarbage()
。但这可能会使您的程序停顿一段时间,因此请选择合适的时机。否则,您可以完全忽略它,只需确保您没有收集对某些长期存在的对象(全局变量,注册表或您自己的字典/缓存)的引用。除非您无意间创建了非常深或无限的递归调用,否则堆栈上的引用会快速删除。无法到达的对象将被自动删除,这就是标记清除垃圾收集器的工作方式。