简体   繁体   中英

How I can load multiple scripts without variables problems

I have a class with which I read Lua and I want to make it so that you can load several scripts at once and do not conflict, that is, the value of Lua variables are saved in the first script when the other is executed.

I expected the program to output it -

print = 123
print = Hi 0
Result = 3
print = Hi 1
Result = 3
print = Hi 2
Result = 3
print = Hi 3
Result = 3

print = Hi 4
Result = 3
print = Hi 5
Result = 3
print = Hi 6
Result = 3
print = Hi 7
Result = 3

print = 123
print = Hi 0
Result = 3
print = Hi 1
Result = 3
print = Hi 2
Result = 3
print = Hi 3
Result = 3

print = Hi 8
Result = 3
print = Hi 9
Result = 3
print = Hi 10
Result = 3
print = Hi 11
Result = 3

But she takes it out -

print = 123
print = Hi 0
Result = 3
print = Hi 1
Result = 3
print = Hi 2
Result = 3
print = Hi 3
Result = 3

print = Hi 4
Result = 3
print = Hi 5
Result = 3
print = Hi 6
Result = 3
print = Hi 7
Result = 3

print = 123
print = Hi 0
Result = 3
print = Hi 1
Result = 3
print = Hi 2
Result = 3
print = Hi 3
Result = 3

print = Hi 4
Result = 3
print = Hi 5
Result = 3
print = Hi 6
Result = 3
print = Hi 7
Result = 3

Here is my code:

    #pragma once

    #pragma comment(lib, "lua53.lib")
    extern "C" {
    #include "lua.h"
    #include "lauxlib.h"
    #include "lualib.h"
    }

    #include <iostream>
    #include <LuaBridge/LuaBridge.h>
    using namespace std;
    using namespace luabridge;
    class Lua_sup
    {
    private:

    string m_name;
    lua_State* L ;
    bool init_state = false;
    inline void PrintError(int run_status)
    {
        switch (run_status)
        {
        case LUA_ERRRUN:
        {

            printf( "LUA: Runtime Error: %s\n", lua_tostring(L, -1));
            break;
        }
        case LUA_ERRSYNTAX:
        {

            printf("LUA: Syntax Error: %s\n", lua_tostring(L, -1));
            break;
        }
        case LUA_ERRMEM:
        {


            printf("LUA: Memory Alloc Error: %s\n", lua_tostring(L, -1));
            break;
        }
        case LUA_ERRERR:
        {

            printf("LUA: Error returning Error: %s\n", lua_tostring(L, -1));
            break;
        }
        default:
        {

            printf("LUA: Unknown Error: %s\n", lua_tostring(L, -1));
            break;
        }
        }
    }
    public:
    Lua_sup(string name, lua_State* s);

    ~Lua_sup();
    void init();
    void test();
    bool get_state() { return init_state; }
    };

//.cpp
#include "Lua_sup.h"


void printMessage(const std::string& s) {
    cout << "print = " << s << endl;
}

string get_string() {
    return "Hi ";
}
Lua_sup::Lua_sup(string name, lua_State* s)
{
    m_name = name;
    L = lua_newthread(s);
}


Lua_sup::~Lua_sup()
{


    lua_close(L);
}

void Lua_sup::init()
{
    //L = luaL_newstate();

    getGlobalNamespace(L).addFunction("printMessage", printMessage);
    int load_status = luaL_loadfile(L, m_name.c_str());
    if (load_status != 0)    {

        cout << "Error";
        PrintError(load_status);
        init_state = false;
    }
    lua_pcall(L, 0, 0, 0); 
    getGlobalNamespace(L).addFunction("get_string", get_string);
    getGlobalNamespace(L).addFunction("printMessage", printMessage);
    init_state = true;
}


void Lua_sup::test()
{
    LuaRef hello_world_sum = getGlobal(L, "hello_world_sum");
    LuaRef plot = getGlobal(L, "plot");
    for (int i = 0; i < 3; i++)
    {
        int result = hello_world_sum(1, 2);
        cout << "Result = " << result << endl;


    }


    int result = hello_world_sum(1, 2);
    cout << "Result = " << result << endl;

    getchar();
}


//my main
#include "Lua_sup.h"
using namespace luabridge;




int main() {
    lua_State* L = luaL_newstate();

    luaL_openlibs(L);


    Lua_sup lua("script.lua", L);
    lua.init();
    lua.test();
    lua.test();
    Lua_sup lua1("123.lua", L);
    lua1.init();
    lua1.test();

    lua.test();
}

I'm Using Luabridge

What you want is to load each file with its own environment. I could tell you with confidence how to do this from Lua, but since you're using C(++) I can only rely on the manual, which says that, when loading Lua code, it will set the environment to "at index LUA_RIDX_GLOBALS in the registry" (I assume you are aware of the C Registry and how to access it).

Since you most likely want the original environment to remain available, you'll have to create a new environment with a metatable set to __index the original one. Keep in mind that this will still allow code to explicitly set global variables via the _G variable, which may be a good thing.

Here's the equivalent code in Lua, which you'll have to port to C:

local meta = {_index=_G}
-- Metatable for the new environment
local function load_sandboxed(file)
  local new_env = setmetatable({}, meta}
  -- Create a new environment with metatable. Missing keys
  -- will be looked for in _G before returning nil
  loadfile(file, "t", new_env)
  -- Load the file with a custom environment.
  -- Only allow text files.
end

Each instance of Lua_sup needs it's own lua_State instance.

int main() 
{
    lua_State* stateA = luaL_newstate();
    luaL_openlibs(stateA);

    Lua_sup lua("script.lua", stateA);
    lua.init();
    lua.test();
    lua.test();

    lua_State* stateB = luaL_newstate();
    luaL_openlibs(stateB );
    Lua_sup lua1("123.lua", stateB );
    lua1.init();
    lua1.test();

    lua.test();

    lua_close(stateA);
    lua_close(stateB);
}

This keeps each script separate and they don't interact.

Note also it's a good idea to close your states when you are done with them

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