简体   繁体   中英

How to close a chunk of Lua code

I wonder if it's possible to only close a chuck of Lua code loaded with luaL_dostring so all the variables inside the chunk can be freed accordingly.

Here's my simple example:

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);

This code prints 2 when I run it but I wonder if it's possible to somehow close(or free) only the firstly loaded chunk from the memory so it prints nil .

Roughly speaking you want to sandbox script A, ie run it with a different global environment than script B. This can easily be done by backing up the global table into the registry and replacing it with an empty table (optionally populate the empty table with whatever you need inside the sandbox). After script A is finished you simply retrieve the old global table from the registry and make it the current global table again.

Apart from that I recommend reducing the usage of globals to an absolute minimum. In fact, I never use any global variables when I write Lua code. Usually I record information in local tables and pass these around. This is probably a more functional style of writing 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM