2012-06-13 11 views
7

Digamos que tengo al menos dos archivos de script lua.Sandboxing Embedded Lua en 5.2/Set Envirenment para funciones de lua.file

test1.lua test2.lua

tanto definir una función init y otras funciones con nombres similares.

¿Cómo puedo cargar cada archivo de script usando C++/c en un entorno separado usando Lua 5.2 para que los mismos nombres de funciones no entren en conflicto? Encontré un código de ejemplo para 5.1 que no funciona para mí (porque setenv se ha ido y lua_setuservalue no parece funcionar)

Muestra aquí Calling lua functions from .lua's using handles?

Básicamente si reemplazo setenv con setuservalue - me sale una violación de acceso.

+0

Esta es una de las razones por las que he pegado con lua 5.1 en mis propios proyectos por ahora. Creo que las funciones v5.2 'load' y' loadfile' te permiten especificar un entorno; probablemente sean el mejor lugar para comenzar a buscar una solución. – Rook

+0

gracias, pero leí sobre carga y carga, sin embargo, no pude encontrar una solución – Steve

+0

'setuservalue' definitivamente no es la función correcta para usar al tratar de manipular el medio ambiente. Sin embargo, los documentos de lua parecen poco claros sobre lo que deberías estar haciendo. 'lua_load' dice que un único upvalue asociado con un fragmento cargado se establece como su entorno, pero no menciona cómo asociar un upvalue con el fragmento de C. Si estaba cargando el fragmento desde dentro de lua, la versión lua de la función 'load' parece que debe configurar el entorno correctamente. – Rook

Respuesta

8

unofficial Lua FAQ tiene una entrada sobre sandboxing en Lua. Supongo que puede transponer esa lógica con la suficiente facilidad a su código C/C++.

Véase también LuaFiveTo on the lua-users wiki.

Corrección

De hecho, no es tan trivial como parecía. Pero al final el punto es simple: cargue su porción, presione la tabla _ENV, use lua_setupvalue(L,-2,1). Lo importante es que la tabla debe estar en la parte superior de la pila.

Como un pequeño ejemplo, por medio de 2 ambientes morosos a _G para la materia de la lectura a través de metatablas:

#include <lua.h> 
#include <lualib.h> 
#include <lauxlib.h> 

int main(void){ 
     lua_State *L = luaL_newstate(); 
     char *file1 = "file1.lua"; 
     char *file2 = "file2.lua"; 

     luaL_openlibs(L); 

     luaL_loadfile(L,file2); // S: 1 
     luaL_loadfile(L,file1); // S: 2 
     lua_newtable(L); // ENV for file 1: S: 321 
     lua_newtable(L); // ENV for file 2: S: 4321 

     //lets have each function have its metatable, where missed lookups are 
     //instead looked up in the global table _G 

     lua_newtable(L); // metatable S: 54321 
     lua_getglobal(L,"_G"); // pushes _G, which will be the __index metatable entry S: 654321 

     lua_setfield(L,-2,"__index"); // metatable on top S: 54321 
     lua_pushvalue(L,-1); // copy the metatable S: 554321 
     lua_setmetatable(L,-3); // set the last copy for env2 S: 54321 
     lua_setmetatable(L,-3); // set the original for env1 S: 4321 
     // here we end up having 2 tables on the stack for 2 environments 
     lua_setupvalue(L,1,1); // first upvalue == _ENV so set it. S: 321 
     lua_setupvalue(L,2,1); // set _ENV for file S: 21 
     // Remaining on the stack: 2 chunks with env set. 
     lua_pcall(L,0,LUA_MULTRET,0); 
     lua_pcall(L,0,LUA_MULTRET,0); 
     lua_close(L); 
     return 0; 
} 

Y para los archivos 2 Lua:

-- file1.lua 
function init() 
     A="foo" 
     print("Hello from file1") 
     print(A) 
end 
init() 

-- file2.lua 
-- this shows that stuff defined in file1 will not polute the environment for file2 
print("init function is",tostring(init)) 
function init() 
     A="bar" 
     print("Hello from file2") 
     print(A) 
end 
init() 
+0

gracias, pero sé que estos recursos, sin embargo no puedo reproducir esto en C/C++ – Steve

+0

De hecho, el problema es que los equivalentes C de 'load' y' loadfile' no tienen una interfaz o documentación tan directa. La página wiki de lua-users también parece estar un poco fuera de datos, y contiene características que nunca llegaron a la especificación 5.2. – Rook

+0

jpjacobs, nos conocimos en lua-irc hoy y como dije, obtuve la solución, ¡pero gracias de nuevo por presentar un ejemplo alternativo! – Steve

0

tanto definir una función init y otras funciones con nombres similares.

En primer lugar, ¿por qué son esas funciones global? Deben ser locales para el guion. Si vas a require en otros archivos, deben crear y devolver una tabla que contenga las funciones que desean exponer.

El idioma moderno al requerir estos archivos es hacer algo como esto:

local Library = require 'library' 

Library.Func1(...) 

Por lo tanto, no contamina el espacio de nombres global Lua. Usas variables locales

Sin embargo, si insiste en usar globales como este, puede hacer exactamente lo que dice la documentación: cambie el primer valor ascendente del fragmento compilado.

Básicamente si reemplazo setenv con setuservalue - obtengo una infracción de acceso.

Por supuesto que sí. Eso no es lo que lua_setuservaluehace.Es para establecer valores asociados con userdata. Lo que quiere se llama apropiadamente lua_setupvalue.

Usando el código de ejemplo que usted cita, la respuesta correcta sería:

lua_setupvalue(L, -2, 1); 
+0

accidentalmente lo descubrí yo mismo - lua_setupvalue (L, -2, 0); ¡se bloquea! - Me salí con el uso de lua_setupvalue (L, -2, 1); - mi conocimiento es limitado y sé exactamente qué es 1 en este contexto. pero parece funcionar, ¿ahora también es posible exponer mi objeto solo en este "espacio de nombres" y no en la tabla global?estoy usando luabind para exponer mis clases y actualmente estoy usando luabind :: globals (myLuaState) ["myObj"] = myObj – Steve

+0

en cuanto a "por qué" son las funciones globales - me gusta crear un sistema de eventos con scripts para múltiples entidades que usan la misma firma de función, por ejemplo, init, dado que los scripts en general no son creados por desarrolladores, quiero hacerlo lo más sencillo posible y no molestar a nadie con librerías o módulos; por eso quiero asegurarme de que cada script se ejecute en su propio entorno, ¡de todos modos no tiene origen! – Steve

+0

@Steve: La documentación no está clara si la función 'lua_setupvalue' toma índices basados ​​en cero o basados ​​en una sola. Parece que están basados ​​en una sola persona. –

Cuestiones relacionadas