c++ - tablas - ¿Llamar a las funciones de lua desde los controladores de.lua?
programa lua download (3)
La función setfenv()
se puede usar para crear un entorno limitado o un entorno para cada archivo cargado.
Este ejemplo muestra que los tres archivos pueden cargarse con funciones en conflicto y que las funciones se pueden llamar en cualquier orden. Código similar podría escribirse en C ++. Este ejemplo solo exporta la función de impresión a cada entorno, es posible que se necesite más en su escenario.
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
Estoy trabajando en un pequeño proyecto tratando de integrar lua con c ++. Mi problema sin embargo es el siguiente:
Tengo varios guiones de lua, vamos a llamarlos s1.lua s2.lua y s3.lua. Cada uno de estos tiene las siguientes funciones: setVars () y executeResults ().
Ahora puedo llamar a un archivo lua a través de LuaL_dofile e inmediatamente después de usar setVars () y / o executeResults (). El problema aquí es que después de cargar s2.lua ya no puedo llamar a las funciones de s1.lua. Esto significaría que tengo que volver a hacer el LuaL_dofile en s1.lua para recuperar el acceso a la función y, al hacerlo, perderé el acceso a las funciones en s2.lua.
¿Hay alguna manera de simplemente cargar todos los archivos lua en una fila, y luego comenzar a llamar a sus funciones a voluntad? Algo como s1-> executeResults () s5-> executeResults () s3-> setVars () etc.
Actualmente ya tengo un sistema implementado usando boost :: filesystem para detectar todos los archivos lua en una carpeta, luego guardo estos nombres de archivos en un vector y luego simplemente itero sobre el vector para cargar cada archivo lua en una fila.
Dejando de lado el llenado del vector con los nombres de archivo lua, mi función de carga de complementos se ve así en este momento:
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;
}
}
}
Para hacerlo un poco más claro, todo lo que tengo en .lua es algo como esto:
-- s1.lua
setVars()
--do stuff
end
executeResults()
--dostuff
end
etc., pero me gustaría poder llamar a setVars () de s1.lua y setVars () de s2.lua después de haber cargado ambos en una fila.
Esto es efectivamente lo que gwell propuso usar la API C:
#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;
}
Guiones de prueba:
-- test1.lua
function init() output = ''test1'' end
function run() print(output) end
-- test2.lua
function init() output = ''test2'' end
function run() print(output) end
Salida:
test1
test2
test2
test1
He omitido todo el manejo de errores por brevedad, pero querrá verificar el valor de retorno de luaL_loadfile
y usar lua_pcall
lugar de lua_call
.
Puede crear un nuevo estado lua_newstate()
para cada archivo. Esto sería más fácil que mi respuesta anterior. Sin embargo, puede tener una penalización de rendimiento.