2012-06-13 2 views
7

Diciamo che ho almeno due file di script lua.Sandboxing Embedded Lua in 5.2/Set Envirenment per Funzioni da lua.file

test1.lua test2.lua

entrambi definire una funzione init e altre funzioni con nomi simili.

Come posso caricare ciascun file di script utilizzando C++/c in un ambiente separato utilizzando Lua 5.2 in modo che gli stessi nomi di funzione non si scontrino: ho trovato un codice di esempio per 5.1 che non funziona per me (perché setenv è scomparso e lua_setuservalue non sembra funzionare)

Esempio qui Calling lua functions from .lua's using handles?

In sostanza se sostituisco setenv con setuservalue - io ottenere una violazione di accesso.

+0

Questo è uno dei motivi per cui ho bloccato con lua 5.1 nei miei progetti, per ora. Credo che le funzioni v5.2 'load' e' loadfile' permettano di specificare un ambiente; sono probabilmente il posto migliore in cui iniziare a cercare una soluzione. – Rook

+0

grazie ma ho letto su load e loadfile tuttavia non sono riuscito a trovare una soluzione – Steve

+0

'setuservalue' non è sicuramente la funzione corretta da utilizzare quando si tenta di manipolare l'ambiente. I documenti lua sembrano in qualche modo poco chiari su ciò che dovresti fare, comunque. 'lua_load' dice che un singolo upvalue associato ad un chunk caricato viene impostato come ambiente, ma non menziona come si va ad associare un upvalue con il chunk di C. Se si stava caricando il blocco da dentro lua, la versione lua di la funzione 'load' sembra che dovrebbe impostare correttamente l'ambiente. – Rook

risposta

8

Il unofficial Lua FAQ ha una voce sulla sandboxing in Lua. La mia ipotesi è che si possa trasporre quella logica abbastanza facilmente al proprio codice C/C++.

Vedere anche LuaFiveTo on the lua-users wiki.

Correzione

Non è infatti così banale come sembrava. Ma alla fine il punto è semplice: carica il tuo chunk, premi il tavolo _ENV, usa lua_setupvalue(L,-2,1). L'importante è che la tabella dovrebbe essere in cima alla pila.

Come un piccolo esempio, utilizzando 2 ambienti inadempienti per _G per le cose di lettura tramite metatables:

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

E per i file di 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

grazie ma conosco queste risorse - tuttavia non riesco a riprodurlo in C/C++ – Steve

+0

In effetti, il problema è che gli equivalenti C di 'load' e' loadfile' non hanno un'interfaccia o una documentazione abbastanza semplice. Anche la pagina wiki di lua-users sembra essere un po 'fuori dai dati, e contiene caratteristiche che non sono mai entrate nella specifica 5.2. – Rook

+0

jpjacobs, ci siamo incontrati oggi a lua-irc e come ho detto ho trovato la soluzione ma grazie ancora per aver tirato fuori un esempio alternativo! – Steve

0

sia definire una funzione init e altre funzioni con nomi simili.

Prima di tutto, perché sono quelle funzioni globale? Dovrebbero essere locali alla sceneggiatura. Se stai andando a require in altri file, dovrebbero creare e restituire una tabella contenente le funzioni che desiderano esporre.

Il linguaggio moderno quando richiedono questi file è quello di fare qualcosa di simile:

local Library = require 'library' 

Library.Func1(...) 

Così, non inquinano lo spazio dei nomi globale Lua. Usa le variabili locali.

Tuttavia, se si insiste a utilizzare globals come questo, è possibile fare esattamente ciò che diceva la documentazione: modificare il primo valore del blocco compilato.

Fondamentalmente se sostituisco setenv con setuservalue - ottengo una violazione di accesso.

Certo che si. Questo non è quello che lua_setuservaluefa.È per l'impostazione dei valori associati a userdata. Quello che vuoi è opportunamente chiamato lua_setupvalue.

Utilizzando il codice di esempio si citano, la risposta corretta sarebbe:

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

ho capito per errore me stesso - lua_setupvalue (L, -2, 0); si blocca! - Sono partito usando lua_setupvalue (L, -2, 1); - La mia conoscenza è limitata e so esattamente cosa 1 è in questo contesto. ma sembra funzionare - ora è anche possibile esporre il mio oggetto solo in questo "spazio dei nomi" e non nella tabella globale?im usando luabind per esporre le mie classi e attualmente im usando luabind :: globals (myLuaState) ["myObj"] = myObj – Steve

+0

come per "perché" sono le funzioni globali - mi piace creare un sistema di eventi con script per più entità che usano la stessa firma della funzione es init, dal momento che gli script non sono generalmente creati dagli sviluppatori, voglio renderlo il più indolore possibile e non disturbare nessuno con librerie o moduli - quindi voglio assicurarmi che ogni script sia eseguito nel suo ambiente - il suo non originario comunque! – Steve

+0

@Steve: la documentazione non è chiara se la funzione 'lua_setupvalue' richiede indici basati su zero o su base singola. Sembra che siano a base unica. –