首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用句柄从.lua中调用lua函数?

使用句柄从.lua中调用lua函数?
EN

Stack Overflow用户
提问于 2010-08-08 06:08:02
回答 3查看 2.8K关注 0票数 1

我正在做一个小项目,试图将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文件名填充向量之前,我的插件加载函数现在看起来是这样的:

代码语言:javascript
复制
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中的所有内容都是这样的:

代码语言:javascript
复制
-- s1.lua

setVars()
--do stuff
end

executeResults()
--dostuff
end

等,但我希望能够在简单地将s1.lua的setVars()和s2.lua的setVars()加载到一行之后调用这两个函数。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-08-09 22:39:37

这就是gwell使用C API提出的有效方案:

代码语言:javascript
复制
#include <stdio.h>

#include "lua.h"

static void
executescript(lua_State *L, const char *filename, const char *function)
{
    /* retrieve the environment from the resgistry */
    lua_getfield(L, LUA_REGISTRYINDEX, filename);

    /* get the desired function from the environment */
    lua_getfield(L, -1, function);

    return lua_call(L, 0, 0);
}

static void
loadscript(lua_State *L, const char *filename)
{
    /* load the lua script into memory */
    luaL_loadfile(L, filename);

    /* create a new function environment and store it in the registry */
    lua_createtable(L, 0, 1);
    lua_getglobal(L, "print");
    lua_setfield(L, -2, "print");
    lua_pushvalue(L, -1);
    lua_setfield(L, LUA_REGISTRYINDEX, filename);

    /* set the environment for the loaded script and execute it */
    lua_setfenv(L, -2);
    lua_call(L, 0, 0);

    /* run the script initialization function */
    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;
}

测试脚本:

代码语言:javascript
复制
-- test1.lua
function init() output = 'test1' end
function run() print(output) end

-- test2.lua
function init() output = 'test2' end
function run() print(output) end

输出:

代码语言:javascript
复制
test1
test2
test2
test1

为简洁起见,我省略了所有错误处理,但您需要检查luaL_loadfile的返回值,并使用lua_pcall而不是lua_call

票数 6
EN

Stack Overflow用户

发布于 2010-08-08 10:58:21

setfenv()函数可用于为加载的每个文件创建sandbox或环境。

此示例显示,所有三个文件都可以加载冲突的函数,并且可以以任何顺序调用这些函数。类似的代码可以用C++编写。此示例仅将打印函数导出到每个环境,在您的场景中可能需要更多。

代码语言:javascript
复制
function newEnv()
  -- creates a simple environment
  return {["print"]=print}
end

local e={} -- environment table
local c    -- chunk variable

-- first instance
c = loadstring([[function f() print("1") end]])
e[#e+1] = newEnv()
setfenv(c, e[#e]) -- set the loaded chunk's environment
pcall(c) -- process the chunk (places the function into the enviroment)

-- second instance
c = loadstring([[function f() print("2") end]])
e[#e+1] = newEnv()
setfenv(c, e[#e])
pcall(c)

-- third instance
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

票数 1
EN

Stack Overflow用户

发布于 2010-08-09 10:54:34

您可以为每个文件创建一个新的状态lua_newstate()。这将比我之前的答案更容易。但是,它可能会有性能损失。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3432231

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档