Calling lua functions from .lua's using handles?
2016-11-18 09:38
183 查看
Calling
lua functions from .lua's using handles?
![](http://static.adzerk.net/Advertisers/054331674d33424abacccb7e6fa6956e.png)
![](http://engine.adzerk.net/i.gif?e=eyJhdiI6NDE0LCJhdCI6NCwiYnQiOjAsImNtIjo0NzE0OTMsImNoIjoxMTc4LCJjayI6e30sImNyIjoxNjM4OTkwLCJkaSI6IjA3NzE0NTI5ZTAwNjRkZjg4ODQ2YzM4NDc2YWViYmZhIiwiZG0iOjEsImZjIjoxOTQzNDQ0LCJmbCI6MjE0MjMxMiwiaXAiOiIxMTMuMTA2LjEwNi45OCIsImt3IjoiYysrLGx1YSxsdWEtYXBpIiwibnciOjIyLCJwYyI6MCwiZWMiOjAsInByIjoxNjA0LCJydCI6MSwicmYiOiJodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzM0NDQzMTIvaG93LXRvLWV4ZWN1dGUtYW4tdW50cnVzdGVkLWx1YS1maWxlLWluLWl0cy1vd24tZW52aXJvbm1lbnQtZnJvbS10aGUtYy1hcGkiLCJzdCI6ODI3NywidWsiOiJ1ZTEtMWYyZjI3NWY5MTlkNDE0MDg0MTZlN2IyMTFmY2FmYTciLCJ6biI6NDMsInRzIjoxNDc5NDMyOTQxNTUzLCJiZiI6dHJ1ZSwicG4iOiJhZHplcms3ODM2MDc0MjIiLCJmcSI6MH0&s=-mGgpycf1MY3KuIzQ7MdjVVlkMM)
up vote0down votefavorite 5 | 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. c++ lua lua-api
| |||
add a comment |
3 Answers
activeoldestvotesup vote5down voteaccepted | 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_loadfileand use lua_pcallinstead of lua_call.
| ||
add a comment |
![](http://static.adzerk.net/Advertisers/b08a4d7b01a04852b914e7904a73b1b8.png)
![](http://engine.adzerk.net/i.gif?e=eyJhdiI6NDE0LCJhdCI6NCwiYnQiOjAsImNtIjo0NzE0OTMsImNoIjoxMTc4LCJjayI6e30sImNyIjoxNjM4OTg5LCJkaSI6ImE2MDdhOTRjOGQ3ZDRmOGViY2M3MDMxZGYxZTkyZGVmIiwiZG0iOjEsImZjIjoxOTQzNDQxLCJmbCI6MjE0MjMxMiwiaXAiOiIxMTMuMTA2LjEwNi45OCIsImt3IjoiYysrLGx1YSxsdWEtYXBpIiwibnciOjIyLCJwYyI6MCwiZWMiOjAsInByIjoxNjA0LCJydCI6MSwicmYiOiJodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzM0NDQzMTIvaG93LXRvLWV4ZWN1dGUtYW4tdW50cnVzdGVkLWx1YS1maWxlLWluLWl0cy1vd24tZW52aXJvbm1lbnQtZnJvbS10aGUtYy1hcGkiLCJzdCI6ODI3NywidWsiOiJ1ZTEtMWYyZjI3NWY5MTlkNDE0MDg0MTZlN2IyMTFmY2FmYTciLCJ6biI6NDQsInRzIjoxNDc5NDMyOTQxNTU0LCJiZiI6dHJ1ZSwicG4iOiJhZHplcmsxNjA2NjE1OTgyIiwiZnEiOjB9&s=y1xD4hbBuq2xDg2UzkRERhG69c4)
up vote1down vote | The setfenv()function can be used to create a sandbox or environment for each file loaded. This example shows that all three files could be loaded with conflicting functions and that the functions can be called in any order. Similar code could be written in C++. This example only exports the print function to each environment, more might be needed in your scenario. 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
| ||||||||||||||||
a comment |
up vote1down vote | You could create a new state lua_newstate()for each file. This would be easier than my previous answer. However, it may have a performance penalty.
| ||||
|
相关文章推荐
- Calling Lua functions : using C++ language
- Calling C++ Functions From Lua(lua调用c/c++)
- Ruby: Calling Ruby's ActiveRecord from Java Using the Bean Scripting Framework
- Calling Web Services From Html Pages using Javascript
- Embedding Lua in C: Using Lua from inside C.
- Calling Lua From a C Program
- AHK Calling an lua-function from ahk
- Calling C++ DLLs from C++ Application Using VS2020
- How to Call Java functions from C Using JNI
- Calling C++ DLLs from C++ Application Using VS2020
- Calling Flex / Actionscript functions from Javascript
- [转]Calling Web Service Functions Asynchronously from a Web Page 异步调用WebServices
- Calling Fortran functions from C++ by means of shared libraries
- Calling Lua function from C++
- calling c++ function from Lua, implement sleep function
- Calling API functions using C#
- 2006-7有价值的Kean博客——Calling ObjectARX functions from a .NET Application(PInvoke)
- 摘录一段《Mastoring Oracle SQL》——PL/SQL Calling Stored Functions from Queries
- calling lua from c in linux
- Calling Lua function from C#