I'm trying to load a table from a string and rather than trying to write a string manipulation function to pull the table apart I was looking at using loadscript.
local testtable = {}
local importStr = [[testtable["Test"] = {
["a"] = 1,
["b"] = 2,
}]]
assert(loadstring(importStr))
If i evaluate testtable at this point its empty. Is there something I need to tell loadstring to allow it to access the local testtable?
the code given to loadstring is the guts of a function
the eventual function runs in the global namespace by default, unless you change its environment
So, try something like this for a starting point:
local primary_definition = [===[
print "compiled code running!"
return {
["a"] = 1,
["b"] = 2,
["c"] = special_data, -- global variable as far as it knows
}
]===]
Passing arguments into your compiled function is a bit tricky. You can put everything in globals (sloppy but easy), or you can assemble the code string around them (precise but can be hard to read/maintain), or you can replace the namespace for that function. For the last method, you stuff all the things you want that function to see into a specific table. Advanced mode: chain that table into the actual global namespace, so that you don't break normal name lookup.
If you don't know all the values you need at the time you create that table, or if you need to change them during runtime, it's just a regular table. This is how you can give your compiled function access to other local names, which loadstring() doesn't see:
local actual_local_variable = 12345
fake_globals.special_data = actual_local_variable
Building the function looks like this:
local func, err = loadstring (primary_definition, "Your Addon's Name")
if func then
-- Make the compiled function see this table as its "globals"
setfenv (func, fake_globals)
-- Running the code in primary_definition returns a newly created table
-- with a/b/c indices
local testtable = assert(func())
else
print ("shit's on fire, yo")
print (err)
end
The argument for your addon's name is just for something to show in stack dumps if loadstring() can't compile your code.
I'll add: if whatever code you're compiling might itself throw errors, you can make your calling code more robust by replacing "assert(func())" with
-- the function inside primary_definition can return up to 3 values
-- before we have to either add more holders, or redo this in a
-- variadic helper function
local okay, ret1, ret2, ret3 = pcall(func)
if okay then
-- ret1 is the table we created
testtable = ret1
-- ret2 and ret3 are reserved for future work when this addon is
-- extended to replace Facebook in-game
else
-- ret1 is an error message
print ("shit continues to be on fire", ret1)
end
function GSSE:importSequence()
local functiondefinition = importStr .. [===[
return Sequences
]===]
GSPrintDebugMessage (functiondefinition, "GS-SequenceEditor")
local fake_globals = setmetatable({
Sequences = {},
}, {__index = _G})
local func, err = loadstring (functiondefinition, "GS-SequenceEditor")
if func then
-- Make the compiled function see this table as its "globals"
setfenv (func, fake_globals)
local TempSequences = assert(func())
if not GSisEmpty(TempSequences) then
local newkey = ""
for k,v in pairs(TempSequences) do
local tver = v.version
if GSisEmpty(tver) then
tver = 1
end
GSAddSequenceToCollection(k, v, tver)
newkey = k
end
names = GSSE:getSequenceNames()
listbox:SetList(names)
listbox:SetValue(newkey)
end
else
GSPrintDebugMessage (err, GNOME)
end
Rollback Post to RevisionRollBack
To post a comment, please login or register a new account.
I'm trying to load a table from a string and rather than trying to write a string manipulation function to pull the table apart I was looking at using loadscript.
If i evaluate testtable at this point its empty. Is there something I need to tell loadstring to allow it to access the local testtable?
I also tried
So, try something like this for a starting point:
Passing arguments into your compiled function is a bit tricky. You can put everything in globals (sloppy but easy), or you can assemble the code string around them (precise but can be hard to read/maintain), or you can replace the namespace for that function. For the last method, you stuff all the things you want that function to see into a specific table. Advanced mode: chain that table into the actual global namespace, so that you don't break normal name lookup.
If you don't know all the values you need at the time you create that table, or if you need to change them during runtime, it's just a regular table. This is how you can give your compiled function access to other local names, which loadstring() doesn't see:
Building the function looks like this:
The argument for your addon's name is just for something to show in stack dumps if loadstring() can't compile your code.
My final code ended up looking like