我想知道是否有可能只关闭装载有luaL_dostring
的Lua代码,以便可以相应地释放块中的所有变量。
这是我的简单示例:
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
。
答案 0 :(得分:2)
大致来说,您想对脚本A进行沙箱处理,即在与脚本B不同的全局环境中运行它。可以通过将全局表备份到注册表中并用一个空表替换它来轻松完成(可选地填充空表)。沙盒内您需要的表格)。脚本A完成后,您只需从注册表中检索旧的全局表,然后再次使其成为当前全局表即可。
除此之外,我建议将全局变量的使用减少到绝对最小值。实际上,在编写Lua代码时,我从不使用任何全局变量。通常,我将信息记录在本地表中并传递给周围。这可能是更functional的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