我正在研究的一个C ++程序是使用lua进行配置。它使用硬编码脚本设置了几个lua函数:
luaL_loadbuffer(pmLuaState, headerscript, strlen(headerscript), "header script");
然后加载配置lua文件(调用前面提到的函数):
luaL_loadfile(pmLuaState, filename)
不幸的是,Lua配置文件使用名为type的全局变量,因此尝试从我的headerscript调用内置的type()函数失败并出现Lua错误:
attempt to call global 'type' (a string value)
由于我的方案的限制,我无法编辑有问题的配置文件。我想知道是否有一种方法可以说明我想要使用内置的type()函数。
我是Lua的新手,所以如果有更好的方法来加载这些脚本以避免这种全局隐藏问题,我会对它开放(但同样,我无法编辑配置脚本)。
Lua版本:5.1.4
答案 0 :(得分:3)
你应该sandbox配置文件,这样它们就不会影响整个程序的全局环境。
使用空表作为luaL_load*()
返回的块上的环境调用lua_setfenv()
。
更新:如果配置文件需要来自全局环境的东西,请用metatables公开它。
在Lua:
setfenv(chunk, setmetatable({__index = _G }))
(阅读手册以了解如何用C语言书写。)
请注意,这种沙盒方法对于不受信任的代码来说太弱了。例如,config可以执行table.concat = myevilfunction
之类的操作。请参阅上面链接的Wiki页面,了解完整的沙盒方法(虽然在您的情况下应该是过度杀戮)。
答案 1 :(得分:3)
修改全局变量后,无法恢复该值 - 也就是说,必须首先阻止脚本设置_G.type,或者预先存储该值。第二个是相对微不足道的
local type = type -- problem solved
或者您可以使用环境来解决此问题。这是一个非常常见的脚本。
local loadedmodules = {}
import = function(filename)
if (loadedmodules[filename]) then
return loadedmodules[filename]
end
local env = {}
local func = loadfile(filename);
local envmeta = {
__index = _G -- changed thanks to comments
}
setmetatable(env, envmeta) -- Allow the imported script to read only our globals
setfenv(func, env) -- set func's _G to env
func() -- Load the script
return loadedmodules[filename] = env -- Set the result and return it.
end
这将是C ++等效的自动标头保护和宏自动作用于定义文件。
从Lua定义此脚本后,您可以从C ++加载它并相对简单地调用它。我不建议从C ++做任何广泛的Lua逻辑,基于堆栈的API非常可怕。