c++ - 如何关闭一大块 Lua 代码
问题描述
我想知道是否可以只关闭一段加载的 Lua 代码,luaL_dostring
以便相应地释放块内的所有变量。
这是我的简单示例:
lua_State *L = luaL_newstate();
luaL_openlibs(L);
luaL_dostring(L, "a = 2"); // Script A
//How close the script A here?
luaL_dostring(L, "print(a)"); // Script B
lua_close(L);
这段代码2
在我运行时打印,但我想知道是否有可能以某种方式仅关闭(或释放)内存中第一个加载的块,以便打印nil
。
解决方案
粗略地说,您希望对脚本 A 进行沙盒处理,即使用与脚本 B 不同的全局环境运行它。这可以通过将全局表备份到注册表中并用空表替换它来轻松完成(可以选择用任何内容填充空表您需要在沙箱内)。脚本 A 完成后,您只需从注册表中检索旧的全局表并再次使其成为当前全局表。
除此之外,我建议将全局变量的使用减少到绝对最低限度。事实上,我在编写 Lua 代码时从不使用任何全局变量。通常我在本地表中记录信息并传递这些信息。这可能是一种更实用的 Lua 编写方式。
#include <iostream>
#include <lua.hpp>
int main() {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
// START SANDBOX
// Push the global table into the registry
lua_pushglobaltable(L);
lua_setfield(L, LUA_REGISTRYINDEX, "globals");
// Push a new empty table and make it the global table
lua_newtable(L);
lua_rawseti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
// Script A
if (luaL_dostring(L, "a = 2") != 0) {
std::cerr << "lua:" << lua_tostring(L, -1) << '\n';
lua_pop(L, 1);
}
// Retrieve the global table from the registry and make it the global table
lua_getfield(L, LUA_REGISTRYINDEX, "globals");
lua_rawseti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
// Optional: Remove the global table from the registry
lua_pushnil(L);
lua_setfield(L, LUA_REGISTRYINDEX, "globals");
// END SANDBOX
// Script B
if (luaL_dostring(L, "print(a)") != 0) {
std::cerr << "lua:" << lua_tostring(L, -1) << '\n';
lua_pop(L, 1);
}
lua_close(L);
}
$ clang++ -Wall -Wextra -Wpedantic -I /usr/include/lua5.2/ test.cpp -llua5.2
$ ./a.out
nil
推荐阅读
- javascript - 是否可以在浏览器上操作环境变量?
- javascript - React Native UseEffect with Dispatch Not Re-Render
- python - 如何在 Django 的 API 中包含运行功能?
- amazon-web-services - 将自定义域路径重定向到 Cloudfront AWS
- ios - 我应该在哪里用 VIPER 在 UICollectionView 中的 didSelectItemAt 中编写逻辑?
- ios - 在 UITextVIew 中下降后无法将单词添加到阿拉伯语行
- docker - 未找到等待的证据
- c - 输入字符后变量自动变为零
- python - Python if else 语句基于符号
- video - 当在 Chrome 浏览器的开发人员工具的网络选项卡中找不到 m3u8 文件时,如何下载 blob 视频文件?