For an answer to anot开发者_Python百科her question, I wanted to load some serialized lua code into a table. The string to be loaded is of this form:
SavedVars = { }
SavedStats = { }
(where each of the {...}
might be any Lua expression, including a table constructor with nested data. I'm assuming it is not calling any (global) functions or using global variables.
What I finally want to have is a table of this form:
{ ["SavedVar"] = { }, ["SavedStats"] = { } }
I do not want to have global variables SavedVars
afterwards.
How to do this most elegantly?
(I already found a solution, but maybe someone has a better one.)
Here is my solution:
-- loads a string to a table.
-- this executes the string with the environment of a new table, and then
-- returns the table.
--
-- The code in the string should not need any variables it does not declare itself,
-- as these are not available on runtime. It runs in a really empty environment.
function loadTable(data)
local table = {}
local f = assert(loadstring(data))
setfenv(f, table)
f()
return table
end
It loads the data string with loadstring
and then uses setfenv
to modify the global environment of the function to a new table. Then calling the loaded function once fills this table (instead of the global environment), which we then can return.
Setting the environment to a new table has the effect that the code can't use any global data at all. I think this is a good way to sandbox the code, but if it is not wanted, you could populate the table before or provide it with some metatable (but unset it before returning the table).
This loading function will also work with serialized data produced like in Saving Tables with Cycles.
精彩评论