我有一个运行Lua脚本的应用程序。每个Lua脚本可能会运行几次。每次按下某个键时,某些脚本甚至可能会运行。
我希望这些脚本在每次运行之间“重置”。即如果用户设置变量Foo,则下次运行时脚本中不应存在Foo,直到用户再次定义它为止。
问题是,如果我想要这样的行为,我需要每次都创建一个新的lua_State,然后每次都打开它,然后每次解析脚本文件,这看起来非常不优化。
加载库可能是一个相当轻量级的操作(我假设),但解析脚本可能不是。
有没有办法重置Lua脚本的状态(即清除用户代码定义的变量)而不创建新的lua_State并重新整理整个Lua脚本文件?我希望在应用程序启动时解析一次脚本文件,因为它们在运行时不会被修改。
谢谢。 :)
编辑:我找到了这个主题,但没有详细说明:http://lua-users.org/lists/lua-l/2006-01/msg00493.html
编辑:lua_setfenv似乎与此有关。我会再多挖一点。
编辑:从LUA 5.2开始,似乎没有更多的lua_setfenv。由于我使用的是5.3,我必须设置环境(即隐藏的表nammed _ENV,其中存储了变量)才能这样做,从而重新加载所有内容,这就是我不想做的事情......
答案 0 :(得分:1)
不幸的是,上次我调查这个时答案是否定的。
您还需要记住,Lua可能会调用库,可能会打开文件,malloc()
内存等,并且任何“重置”文件都可以。需要处理关闭这些文件,释放内存等等。
作为重置'的替代方案。在Lua状态下,您可以简单地组织代码,这样就不需要重置;这显然需要以特定的方式编写Lua代码。一种方法是坚持你的Lua代码完全(或几乎完全)包含在函数中,并为每个动作调用一个或多个函数。函数外部的代码可能(例如)返回一个Lua表,该表包含对特定入口点的调用的引用;这只会被调用一次。调用时,函数将自行清除,包括清除任何库分配项,打开文件等。应避免使用全局变量(除非常量)。我们成功地使用这种方法来确保Lua只被解析一次,入口点确定一次,但相对较小的函数可以非常快速地调用而且开销很小。
在您建议的注释中,您可以将Lua代码词法包装在功能块中。我认为这不如上述方法灵活,并具有以下缺点:
你失去了做一次初始化的机会。 (例如,从磁盘读取固定常量)
如果用户在代码中插入(例如)不匹配的end ... function B()
您将自己限制在每个Lua州的一个入口点。
这确实意味着Lua代码必须以不同的方式编写(实质上Lua编码器以所需的形式提供代码)。解决此问题的一种可能方法是使用固定框架执行此操作,并在代码中require
作为库调用。我没有尝试过那种方法。
答案 1 :(得分:1)
如果要确保每次脚本调用时lua_State都相同,还可以尝试以下适用于我的情况的方法:
请注意,这仅处理完全包含在Lua数据结构中的资源,而不处理通过Lua或Lua库以任何方式引用的“外部”资源(例如,文件描述符,userdata等)
因此,在我的情况下,我还通过替换globals表将脚本编写器的功能限制在某些沙箱中,仅提供对上述用法安全的操作。
使用这种方法,在每次“运行”之后,重置基本上可以归结为一些scaleLinear(-1)
调用,因此,复制脚本的Lua结构所使用的内存所需的时间长。
答案 2 :(得分:0)
你不能清除lua_State吗?删除所有线程和手动设置的全局变量。您可能需要将用户环境与全局环境分开。