lua中使用require后全局变量丢失的问题

问题是,使用"require"关键字会清除同一文件中定义的所有全局变量。

我正在C++项目中使用Lua 5.3进行开发。我的Lua脚本风格是:

1.所有Lua代码都包含一个公共库文件,以及多个充当函数的小文件。

2.当程序启动时,Lua公共库会被编译并运行,在Lua状态中留下其全局变量。然后编译小文件,但不执行。

3.当程序到达某一点时,相关的小Lua文件将被调用(就像我说的,每个小文件都是一个函数)。在小Lua文件中使用公共库中定义的全局函数和变量。这就是为什么程序启动时我编译并执行公共库的原因。

4.我非常确定我只使用了一个Lua_State。

它一直工作得很好,直到我决定将公共库拆分为多个文件,并在主文件中使用"require"。当程序启动时,将编译并执行主文件。

没有任何代码更改,只是添加了一些"require"。奇怪的事情发生了:所有全局变量和全局函数都丢失了。当在小Lua文件中调用全局函数时,会引发一个"called a nil value"错误。

然后我进行了一个实验,我删除了主库文件中的所有"require"行,结果发现主库中定义的全局函数工作得非常好。然后,我要求一个名为"simple.lua"的空文件,定义在主库中的全局函数丢失了,无法从小Lua文件中调用。

如何解释这个问题?为什么"require"关键字会清除同一文件中定义的所有全局变量?

在Lua库中:

require("simple")
function foo()
    return 1+1
end

在小Lua文件中:

return foo()

结果:尝试调用一个空值(全局'foo')

删除"require"后,在Lua库中:

function foo()
    return 1+1
end

结果:没有错误发生,返回2。

C++端代码:

Lua公共库编译和执行:

int code = luaL_loadbuffer(L, s, strlen(s), "commonlib");
if(code != 0) {
    std::string error = lua_tostring(L, -1);
    lua_pop(L, 1);
    return error;
}
code = lua_pcall(L, 0, 0, 0);
if(code > 0)
{
    std::string ret = lua_tostring(L, -1);
    lua_pop(L, 1);
    return ret;
}
else
    return "";     //空字符串表示没有错误

Lua小函数文件编译:

int code = luaL_loadbuffer(L, s, strlen(s), "RULE1");
if(code != 0) {
    std::string error = lua_tostring(L, -1);
    lua_pop(L, 1);
    return error;
}
else
{
    return "";    //返回空值表示没有错误
}

在两个代码中的L是相同的Lua状态(否则删除"require"时不会起作用)。编译后,小文件函数在堆栈顶部被保存在全局寄存器中,并有参考变量"ref"。 调用Lua小文件时,将ref推入堆栈,使用lua_pcall,没有什么特别的。

点赞
用户8318938
用户8318938

Resolved the problem by myself.

因为复制/粘贴错误,之后会创建第二个lua虚拟机。这很令人困惑,因为如果没有“require”,一切都还好。这只是一个巧合。

我从中学到的是:始终仔细检查复制/粘贴的代码。

2019-05-21 11:47:58