从 .lua 文件中使用句柄调用 Lua 函数?
我正在做一个小项目,试图将lua与c++集成在一起。 但是,我的问题如下:
我有多个lua脚本,让我们称之为s1.lua s2.lua和s3.lua。每个脚本都有以下函数:setVars()和executeResults()。
现在,我能够通过LuaL_dofile调用lua文件,并在使用setVars()和/或executeResults()之后立即使用它们。然而,这里的问题在于,在加载s2.lua后,我不能再调用s1.lua的函数。这意味着我必须重新对s1.lua使用LuaL_dofile以重新获得对函数的访问权限,并通过这样做失去对s2.lua中函数的访问权限。
是否有一种方法可以简单地按顺序加载所有lua文件,然后随意开始调用它们的函数?类似于s1-> executeResults()s5-> executeResults()s3-> setVars()等。
我目前已经有一个系统,使用boost::filesystem检测文件夹中的所有lua文件,然后将这些文件名保存在一个向量中,然后简单地迭代向量以按顺序加载每个lua文件。
放弃使用lua文件名填充向量,我的插件加载函数目前如下所示:
void Lua_plugin::load_Plugins(){
std::vector<std::string>::const_iterator it;
for (it=Lua_PluginList.begin(); it!=Lua_PluginList.end(); it++){
std::cout<<"File loading: " << *it << std::endl;
std::string filename = *it;
std::string filepath = scriptdir+filename;
if (luaL_loadfile(L, filepath.c_str()) || lua_pcall(L, 0, 0, 0)) {
std::cout << "ScriptEngine: error loading script. Error returned was: " << lua_tostring(L, -1) << std::endl;
}
}
}
为了更清楚,所有我在.lua中的内容都像这样:
-- s1.lua
setVars()
--do stuff
end
executeResults()
--dostuff
end
等等,但我想能够在简单地连续加载它们之后调用s1.lua的setVars()和s2.lua的setVars()。
原文链接 https://stackoverflow.com/questions/3432231
你可以为每个文件创建一个新的状态lua_newstate()
。这比我的先前回答要简单。然而,这可能会有性能损失。
这实际上是使用 C API 所提出的 gwell 输 出:
#include <stdio.h>
#include "lua.h"
static void
executescript(lua_State *L, const char *filename, const char *function)
{
/* 从注册表检索出环境 */
lua_getfield(L, LUA_REGISTRYINDEX, filename);
/* 从环境中获取所需函数 */
lua_getfield(L, -1, function);
return lua_call(L, 0, 0);
}
static void
loadscript(lua_State *L, const char *filename)
{
/* 将 Lua 脚本加载到内存中 */
luaL_loadfile(L, filename);
/* 创建一个新的函数环境并将其存储在注册表中 */
lua_createtable(L, 0, 1);
lua_getglobal(L, "print");
lua_setfield(L, -2, "print");
lua_pushvalue(L, -1);
lua_setfield(L, LUA_REGISTRYINDEX, filename);
/* 为加载的脚本设置环境并执行它 */
lua_setfenv(L, -2);
lua_call(L, 0, 0);
/* 运行脚本初始化函数 */
executescript(L, filename, "init");
}
int
main(int argc, char *argv[])
{
lua_State *L;
int env1, env2;
L = (lua_State *) luaL_newstate();
luaL_openlibs(L);
loadscript(L, "test1.lua");
loadscript(L, "test2.lua");
executescript(L, "test1.lua", "run");
executescript(L, "test2.lua", "run");
executescript(L, "test2.lua", "run");
executescript(L, "test1.lua", "run");
return 0;
}
测试脚本:
-- test1.lua
function init() output = 'test1' end
function run() print(output) end
-- test2.lua
function init() output = 'test2' end
function run() print(output) end
输出:
test1
test2
test2
test1
我为了简洁起见省略了所有的错误处理, 但您需要检查 luaL_loadfile
的返回值并使用 lua_pcall
。
- 如何在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 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
setfenv()
函数可以用于创建每个文件加载的 沙箱或环境。下面的示例展示了三个文件加载相互冲突的函数,且这些函数可以按任意顺序被调用。类似的代码也可以用 C++ 编写。这个示例仅导出了 print 函数到每个环境中,在您的场景中需要的可能会更多。
function newEnv() -- 创建一个简单的环境 return {["print"]=print} end local e={} -- 环境表格 local c -- chunk 变量 -- 第一个实例 c = loadstring([[function f() print("1") end]]) e[#e+1] = newEnv() setfenv(c, e[#e]) -- 设置所加载 chunk 的环境 pcall(c) -- 处理 chunk (将函数放入环境中) -- 第二个实例 c = loadstring([[function f() print("2") end]]) e[#e+1] = newEnv() setfenv(c, e[#e]) pcall(c) -- 第三个实例 c = loadstring([[function f() print("3") end]]) e[#e+1] = newEnv() setfenv(c, e[#e]) pcall(c) pcall(e[3].f) --> 3 pcall(e[2].f) --> 2 pcall(e[1].f) --> 1 pcall(e[1].f) --> 1 pcall(e[2].f) --> 2 pcall(e[3].f) --> 3