如何关闭Lua代码块

时间:2018-07-18 07:50:51

标签: c++ lua

我想知道是否有可能只关闭装载有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

1 个答案:

答案 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