グラフィック API を Lua に公開する Love2d Lua ゲーム エンジンを使用しています。ゲーム ワールドのすべてのセーブ データを含む巨大なハッシュ テーブルをシリアル化しようとしています。このハッシュにはいくつかの関数が含まれており、これらの関数のいくつかは Love2d C 関数を呼び出します。
ハッシュ内の関数をシリアル化するために、string.dump を使用し、loadstring でそれらをロードし直します。これは純粋な Lua 関数ではうまく機能しますが、Love2d API のようなラップされた C 関数を呼び出す関数をシリアル化してロードバックしようとすると、loadstring は nil を返します。
Love2d のグラフィック エンジンを介して画面に「hello, world」を描画する次の簡単なプログラムを考えてみましょう。
function love.load()
draw = function()
love.graphics.print('hello, world', 10, 10)
end
end
function love.draw()
draw()
end
これを実現したいと考えています:
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
これを行うと、コンパイルされていない Lua と Lua バイトコードが混在するディスク上の Lua ファイルに書き込みます。これは次のようになります。
draw = load([[^[LJ^A^@
@main.lua2^@^@^B^@^B^@^D^E^B^B4^@^@^@%^A^A^@>^@^B^AG^@^A^@^Qhello, world
print^A^A^A^B^@^@]])
この方法は、C モジュールを呼び出さない Lua 関数でうまく機能します。この例は機能するため、これが問題であると考えられます。
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
Love2d グラフィック メソッドを呼び出す代わりに、コンソールに出力します。
さらにテストを重ねた結果、この例が機能することがわかり、混乱しました。
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
ここでは、実際に関数をディスクに書き出すのではなく、単にダンプしてからすぐにロードし直します。おそらく犯人はバイナリ書き込みモード フラグを設定してデータを書き出していなかったのではないかと考えました ( "wb"
) が、Linux を使用しているため、このフラグは効果がありません。
何か案は?