从.lua的使用句柄调用lua函数? [英] Calling lua functions from .lua's using handles?

查看:305
本文介绍了从.lua的使用句柄调用lua函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个小项目,试图将lua与c ++集成。
然而我的问题如下:



我有多个lua脚本,让他们称为s1.lua s2.lua和s3.lua。每个都有以下函数:setVars()和executeResults()。



现在我可以通过LuaL_dofile调用lua文件,和/或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< 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:错误加载脚本。返回的错误是:< lua_tostring(L,-1)< std :: endl;
}
}
}

清除,所有我在.lua的是这样的:

   -  s1.lua 

setVars()
--do stuff
end

executeResults()
--dostuff
end

等等,但我想能够调用s1.lua的setVars()和s2.lua的setVars

解决方案

这实际上是使用C API建议的 b
$ b

  #include< stdio.h> 

#includelua.h

static void
executioncript(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);

/ *运行脚本初始化函数* /
executioncript(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);

executioncript(L,test1.lua,run);
executioncript(L,test2.lua,run);
executioncript(L,test2.lua,run);
executioncript(L,test1.lua,run);

return 0;
}



测试脚本:

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

输出:

  test1 
test2
test2
test1


$ b $ p

为了简洁,省略了所有的错误处理,但是你需要检查返回值 luaL_loadfile 并使用 lua_pcall 而不是 lua_call / p>

I'm working on a small project trying to integrate lua with c++. My problem however is as follows:

I have multiple lua scripts, lets call them s1.lua s2.lua and s3.lua. Each of these has the following functions: setVars() and executeResults().

Now I am able to to call a lua file through LuaL_dofile and immediately after use setVars() and/or executeResults(). The problem here however is that after I load s2.lua I can no longer call the functions of s1.lua. This would mean I have to redo the LuaL_dofile on s1.lua to regain access to the function and by doing so I lose access to the functions in s2.lua.

Is there a way to simply load all lua files in a row, and afterwards start calling their functions at will? Something like s1->executeResults() s5->executeResults() s3->setVars() etc.

I currently already have a system in place using boost::filesystem to detect all lua files in a folder, I then save these files names in a vector and then simply iterate over the vector to load each lua file in a row.

Foregoing the filling of the vector with lua file names my plugin load function looks like this at the moment:

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;
  }
 }
}

To make it a bit more clear, all I have in the .lua's is something like this:

-- s1.lua

setVars()
--do stuff
end

executeResults()
--dostuff
end

etc, but I would like to be able to call s1.lua's setVars() and s2.lua's setVars() after simply having loaded both in a row.

解决方案

This is effectively what gwell proposed using the C API:

#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;
}

Test scripts:

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

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

Output:

test1
test2
test2
test1

I omitted all error handling for brevity, but you'll want to check the return value of luaL_loadfile and use lua_pcall instead of lua_call.

这篇关于从.lua的使用句柄调用lua函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆