We are using the Love2d Lua game engine that exposes a graphics api to Lua. We are trying to serialize a giant hash table that contains all the save game data for the game world. This hash includes some functions, and some of these functions call Love2d C functions.
In order to serialize the functions in the hash, we use string.dump, and load them back in with loadstring. This works well for pure Lua functions, but when we try to serialize and then load back in a function which calls a wrapped C function such as one in the Love2d api, loadstring returns nil.
Consider the following simple program that draws "hello, world" to the screen via Love2d's graphics engine:
function love.load()
draw = function()
love.graphics.print('hello, world', 10, 10)
end
end
function love.draw()
draw()
end
We would like to be able to do this:
function love.load()
draw_before_serialize = function()
love.graphics.print('hello, world', 10, 10)
end
out = io.open("serialized.lua", "wb")
out:write('draw = load([[' .. string.dump(draw_before_serialize) .. ']])')
out:close()
require "serialized"
end
function love.draw()
draw()
end
Doing this writes to a Lua file on disk that contains a mix of non-compiled Lua and Lua bytecode, which looks something like this:
draw = load([[^[LJ^A^@
@main.lua2^@^@^B^@^B^@^D^E^B^B4^@^@^@%^A^A^@>^@^B^AG^@^A^@^Qhello, world
print^A^A^A^B^@^@]])
This method works fine with Lua functions that do not call C modules. We think that this is the problem because this example does work:
function love.load()
draw_before_serialize = function()
print('hello, world')
end
out = io.open("serialized.lua", "wb")
out:write('draw = load([[' .. string.dump(draw_before_serialize) .. ']])')
out:close()
require "serialized"
end
function love.draw()
draw()
end
Instead of calling the Love2d graphics method, it does a print to the console.
After more testing, we were confused to find that this example does work:
function love.load()
draw_before_serialize = function()
love.graphics.print('hello, world', 10, 10)
end
draw = load(string.dump(draw_before_serialize))
end
function love.draw()
draw()
end
Here we don't actually write out the function to disk, and instead just dump it and then immediately load it back. We thought that perhaps the culprit was not writing out the data with the binary write mode flag set ("wb"
), but since we are on Linux this flag has no effect.
Any ideas?
require
? [since you are depending ondraw
being defined in the global environment] – Zibeline[[' .. string.dump(draw_before_serialize) .. ']]
is not necessarily going to work. The dump you get could contain anything, including the]]
characters. That would terminate the string early, thus breaking things. – Alienage](=*)]
and then framed the dump with one=
more than the maximum number of=
's found with the match. – Toddle