如何将lua函数块转储到字符串?
function test(a, b)
local c = a + b
return c
end
print( type(test) ) --> function
print( test ) --> function: 0053B108
print( dumpToString(test) )
我希望dumpToString结果如下:
function test(a, b)
local c = a + b
return c
end
怎么做?
=== update1 ===
我想自动记录并注入代码。
答案 0 :(得分:4)
您没有说为什么您想要这样做,这可能很重要。你可以将一个函数转储到一个字符串,它只是一个非常易读的字符串;你可以这种方式存储和传输你的功能(在兼容的Lua引擎之间):
string.dump(function() print "Hello" end)
答案 1 :(得分:4)
没有简单的答案(毕竟那些年,仍然)。我将详细说明替代方案。
1考古学教授的回答(以及一些反汇编):
这个古老问题的答案在于primodial one。即,luadec。当时可能是在停机时间,但是,至少截至目前,还有一个updated version,它处理lua 5.1-.3。
此外,string.dump
不提供完整的乱码,它以机器指令的原始字节提供程序代码,您可以更好地表示luac -l -p <filename>
的那些代码。
Vm代码没有很好地记录,但人们确实把一些东西放在一起here。 Luajit在其自己的指令集上有更好的文档。
从vm重建代码是luadec的作用。从理论上讲,您也可以将自己的指令拼接成转储字符串。
然而,无论你对字节码做什么技巧,它都会遇到不同解释器之间的不兼容性,包括不同版本的lua本身。
<强> 2。实际上正在做X
将函数转换为字符串是一个非常特殊的愿望(除非您正在进行代码生成,在这种情况下,您首先已经有了字符串)。
&#34;记录并注入代码&#34;确实是非常普遍的X,这可能保证Y得以解决。但单一案例可以涵盖单一案例。
Lua语言非常灵活,例如,您可以通过将其作为对象来跟踪示例中值x
的流程:
local to2number = tonumber
tonumber= function(o)
local r= to2number(o)
if not r then
local m= getmetatable(o)
if m and m.__tonumber then
r=m.__tonumber(o)
end
end
return r
end
local number
number={
new=function(n)
return setmetatable({n},number)
end,
__add=function(me,other)
print("I'm "..tostring(me).." and I'm being added to "..tostring(other))
local o=tonumber(other)
return number.new(me[1]+o)
end,
__tonumber=function(me) return me[1] end,
__tostring=function(me) return tostring(me[1]) end,
}
test(number.new(4), number.new(10))
如上例所示,您可以通过更改函数的环境来注入行为。也就是说,我已经重新定义了全局函数tonumber
。您可能希望在不同的环境中完全打包该功能:
local test = function() print"hello" end
local newenv={print=function(s) print(s..'world') end}
setfenv(test,newenv)--this is lua 5.1, luajit, good luck with upvalues
local test = load(string.dump(test),nil,nil,newenv)--this is lua 5.2-5.3, good luck with upvalues
test()
对于旧版本,您必须处理可能引用您尝试重新定义的全局函数的upvalues。对于较新的版本,您必须处理在转储加载过程中丢失的upvalues。
第3。阅读文件
最后,正如其他人所说,如果你有权访问源代码,你可以尝试从中找到函数定义。除非它是单个函数定义或单个返回文件,否则任务可能最终等同于重新实现lua解析器。这些功能不止一个,但它们并没有考虑到这些功能,因此可能需要一些工作来重新调整其代码。
如果所有的功能都由你自己定义并且你愿意稍微克制一下,你可以再次使用lua metatables,在编码阶段解决问题:
local def=function(code,env)
env=env or _ENV
local compiled,q=load("return "..code,nil,nil,env)
if not compiled then error(q) end
local f=compiled()
return setmetatable({code=code},{__call=function(me,...) return f(...) end})
end
local test=def[[function(a,b)
return a+b
end]]
print(test(2,3))
然而,定义upvalues会很棘手。
答案 2 :(得分:2)
你没有。 Lua不会将编译过的Lua脚本作为原始文本存储在任何地方。并且,由于它是一种小型脚本语言,它也没有提供反编译自己的字节码的机制。
答案 3 :(得分:1)
好吧,您可以将多行代码存储在一个字符串变量中。只需使用双方括号而不是引号。
chunk = [[
function test(a, b)
local c = a + b
return c
end
]]
答案 4 :(得分:-2)
您可以通过
获取程序的源代码local source_code = io.open(arg[0]):read'*a'
并解析它以找到您的函数定义 它仅在从命令行运行lua并将源文件作为参数传递时才有效,而不是字节码文件。