Lua 5.2 的C API中将沙盒化运用于不同的对象
2020-8-29 13:51:20
收藏:0
阅读:165
评论:1
考虑以下使用 Lua C API 的 C ++ 代码:
#include <string>
#include <cassert>
#include <lua/lua.hpp>
class AwesomeThing
{
lua_State* _lua;
std::string _name;
public:
AwesomeThing(lua_State* L, const std::string& name, const std::string& luafile)
: _lua{ L },
_name{ name }
{
assert(luaL_loadfile(_lua, luafile.c_str()) == 0); // 1:chunk
lua_newtable(_lua); // 1:chunk, 2:tbl
lua_newtable(_lua); // 1:chunk, 2:tbl, 3:tbl(mt)
lua_getglobal(_lua, "_G"); // 1:chunk, 2: tbl, 3:tbl(mt), 4:_G
lua_setfield(_lua, 3, "__index"); // 1:chunk, 2: tbl, 3:tbl(mt)
lua_setmetatable(_lua, 2); // 1:chunk, 2: tbl
lua_setupvalue(_lua, -2, 1); // 1:chunk
if (lua_pcall(_lua, 0, 0, 0) != 0) // compiled chunk
{
auto error = lua_tostring(_lua, -1);
throw std::runtime_error(error);
}
lua_setglobal(_lua, _name.c_str()); // 空堆栈
}
void init()
{
lua_getglobal(_lua, _name.c_str()); // 1:env
assert(lua_isnil(_lua, 1) == 0);
lua_getfield(_lua, 1, "onInit"); // 1:env, 2:func
assert(lua_isnil(_lua, 2) == 0);
assert(lua_isfunction(_lua, 2) == 1);
assert(lua_pcall(_lua, 0, LUA_MULTRET, 0) == 0); // 1:env, 2:retval
lua_pop(_lua, 1); // -1:env
lua_pop(_lua, 1); // 空堆栈
assert(lua_gettop(_lua) == 0);
}
};
int main()
{
lua_State* L = luaL_newstate();
luaL_openlibs(L);
AwesomeThing at1(L, "thing1", "file1.lua");
AwesomeThing at2(L, "thing2", "file2.lua");
at1.init();
at2.init();
return 0;
}
使用两个非常基本的 Lua 文件:
file1.lua
function onInit()
print("init file1")
end
file2.lua
function onInit()
print("init file2")
end
作为结果,我在 at2 的构造函数调用中得到一个“lua_pcall”错误:_尝试调用表值
在我注释掉所有关于 at2 的引用/调用后,我在 at1 的 init() 中得到一个错误,在 lua_getfield(_lua, 1, "onInit") 处:PANIC: unprotected error in call to Lua API (attempt to index a nil value)
我感觉我在处理沙盒时漏掉了一些基本的东西,我已经尽力遵循我在网上找到的一些其他 Lua 5.2 沙盒示例,但目前没有什么帮助。
点赞
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

在我自己调试代码后,我成功修复了它,并且错误似乎只来自于几个地方。
lua_pcall会从堆栈中弹出被调函数,但是在你的代码中,在lua_pcall之后你假设函数仍然在堆栈上。这会导致不良的堆栈操作。init()中的lua_getfield调用也无法按预期工作,因为函数块没有名为onInit的字段,而环境变量表有。修复构造函数需要按相反的顺序创建环境变量表并加载块(函数),使得函数调用后环境变量表留在堆栈上:
lua_newtable(_lua); // 1:tbl assert(luaL_loadfile(_lua, luafile.c_str()) == 0); // 1:tbl, 2:chunk lua_newtable(_lua); // 1:tbl, 2:chunk, 3:tbl(mt) lua_getglobal(_lua, "_G"); // 1:tbl, 2:chunk, 3:tbl(mt), 4:_G lua_setfield(_lua, 3, "__index"); // 1:tbl, 2:chunk, 3:tbl(mt) lua_setmetatable(_lua, 1); // 1:tbl, 2:chunk lua_pushvalue(_lua, 1); // 1:tbl, 2:chunk, 3:tbl lua_setupvalue(_lua, -2, 1); // 1:tbl, 2:chunk if (lua_pcall(_lua, 0, 0, 0) != 0) // compiled chunk { auto error = lua_tostring(_lua, -1); throw std::runtime_error(error); } // 1:tbl lua_setglobal(_lua, _name.c_str()); // empty stack然后在
init()中,因为你使用了LUA_MULTRET,只需通过使用lua_settop(_lua, 0)替换两个弹出调用来清除堆栈。