Lua - 重置脚本的状态而不需要重新解析它
我有一个运行 Lua 脚本的应用程序。每个 Lua 脚本可能会运行多次。有些脚本甚至可能每次按键时都会运行。
我希望在每次运行之间重置这些脚本。也就是说,如果用户设置了一个变量 Foo,那么在下一次运行时脚本中就不应该存在 Foo,直到用户再次定义它。
问题在于,如果我想要这样的行为,就需要每次创建一个新的 lua_State,然后每次都打开库,每次解析脚本文件,这显然是非常不优化的。
加载库可能是一个相当轻量级的操作(我认为),但解析脚本可能不是。
有没有一种方法可以重置 Lua 脚本的状态(即清除用户定义的变量),而不需要创建一个新的 lua_State 并重新解析整个 Lua 脚本文件?我希望在应用程序启动时只需要解析一次脚本文件,因为它们在运行时不会被修改。
谢谢。:)
EDIT : 我找到了这个帖子,但它并没有详细说明如何做到这一点:http://lua-users.org/lists/lua-l/2006-01/msg00493.html
EDIT : lua_setfenv 似乎与此相关。我会再深入一些。
EDIT : 看起来在 LUA 5.2 中已经没有 lua_setfenv 了。由于我正在使用 5.3,我需要设置环境(即一个名为 _ENV 的隐藏表,其中存储变量)才能做到这一点,并重新加载所有内容,而这正是我不想做的...
上次我了解过这个问题,但很遗憾,答案是否定的。
你还需要记住 Lua 可能调用库,打开文件,调用 malloc() 等等操作,任何“重置”的操作都需要关闭这些文件,释放这些内存等等。
作为重置 Lua 状态的替代方式,你可以简单地组织你的代码,使其不需要重置;这显然需要特定的 Lua 代码编写方式。一种方法是坚持让你的 Lua 代码完全(或几乎完全)包含在函数中,并针对每个动作调用一个或多个函数。函数外的代码(例如)可能返回一个 Lua 表,其中包含调用特定入口点的引用;这只会被调用一次。当调用函数时,它会自清,包括清理任何库分配的项,打开文件等等。应该避免使用全局变量(除非是常量)。我们成功地使用这种方法来确保仅解析一次 Lua,仅在入口点确定一次,但可以非常快速地调用相对较小的函数,并且带有很少的开销。
在评论中,你建议将 Lua 代码在函数块中进行词法包装。我认为这种方法比上述方法不够灵活,具有以下缺点:
你失去了进行“一次性初始化”的机会(例如从磁盘读取一个固定常量)
如果用户插入(例如)一个不匹配的
end ... function B()在他们的代码中,你会面临不可预测的问题你将自己限制在一个 Lua 状态的一个入口点中。
这意味着 Lua 代码必须以不同的方式编写(实质上,Lua 编写者正在以所需的形式提供代码)。可行的一种方法是使用一个固定的框架来实现这一点,并在需要被调用的代码中使用 require。我没有尝试过这种方法。
如果您想确保每次脚本调用时 lua_State 是相同的,那么您还可以尝试以下方法,这在我的情况下运行正常:
- 为 lua_newstate 传递自定义内存分配器,该分配器从内存池分配内存
- 在解析脚本之后,在第一次“运行”之前,在某个其他内存位置创建内存池的备份
- 在每个“运行”之后,从备份中还原内存池,回到原始位置
请注意,这仅关注完全包含在 Lua 数据结构中的资源,而不涉及从 Lua 或 Lua 库以任何方式引用的“外部”资源(例如文件描述符、用户数据等)。
因此,在我的情况下,我还通过替换全局表来限制脚本编写者的能力,只提供对上述用法认为安全的操作。
使用这种方法,重置基本上归结为每次“运行”后一些 memcpy 调用,因此需要复制为脚本使用的 Lua 结构体的内存所需的时间。
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
问题描述
无法清除
lua_State?删除所有线程和手动设置的全局变量。您可能需要将用户环境与全局环境分开。翻译结果
Can't you clear the lua_State? Remove all threads and the manually set globals. You might need to have the user environment separate from the global environment.
难道您不能清除
lua_State吗?请删除所有线程和手动设置的全局变量。您可能需要让用户环境与全局环境分开。