【问题标题】:Lua: Get function sourceLua:获取函数源
【发布时间】:2013-12-16 04:13:20
【问题描述】:

我正在开发一个用于序列化/反序列化的系统,并且我正在尝试让一些真正花哨的东西与函数一起使用。我的目标是以人类可读和可逆的方式序列化包含函数的对象(序列化文件需要在 loadfile() 步骤之后进行处理)。我需要一种方法来获取函数的实际来源,看起来我不能总是使用 debug.getinfo() 来做到这一点。

我知道 debug.getinfo() 将给出定义它的文件和行(或函数的源,取决于它的来源)。有没有办法从该文件中读取函数文本?我愿意使用某种解析器实用程序来做到这一点。也许有用于解析 Lua 代码的 Lua 包?

也许有办法让 loadfile() 或 require() 在某处自动保留函数源?

是的,我知道你可以从 debug.getinfo 中获取各种信息,但是它无法处理通过 stdin 加载的函数...

uberblah@glade-m:~$ lua
Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
> a = function() print("hello, world!") end
> require("serpent")
> s = require("serpent")
> =s.block(debug.getinfo(a))
{
  currentline = -1,
  func = loadstring("LuaQ\000\000\000\000\000\000\000\000\000=stdin\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000A@\000\000@\000\000�\000\000\000\000\000\000\000\000\000\000\000print\000\000\000\000\000\000\000\000hello, world!\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000",'@serialized') --[[function: 0x2068a30]],
  lastlinedefined = 1,
  linedefined = 1,
  namewhat = "",
  nups = 0,
  short_src = "stdin",
  source = "=stdin",
  what = "Lua"
} --[[table: 0x206cf80]]
> f = io.open("stdin", "r")
> =f
nil

来自标准输入的源解决方​​案... 1)捕获所有STDIN,将其写入文件 2)从该文件加载信息,而不是从标准输入 3) debug 将跟踪该文件中的函数行号

【问题讨论】:

  • 你真的要使用标准输入(这是控制台输入,所以 io.open("stdin") 不会做你想要的)?或加载模块的脚本?如果后者可能会更容易。为什么需要这种能力?也许还有另一种方式。此外,如果您使用 lhf 的答案,您可以读取“源”中指定的文件并直接读取源(因为您有 linedefined 等)。
  • 我知道,如果不是因为这种烦人的需要从标准输入中获取函数,我可以相对轻松地加载函数。但是,我计划使用从标准输入读取的函数,因为我正在为视频游戏编写调试控制台,并且来自该控制台的输入(用 C 编写)被重定向到标准输入。我想很少有人需要从标准输入中读取,我可以在调试控制台和 Lua 之间获得某种缓冲区(该缓冲区可以保存到文件中以进行调试)。很抱歉造成混乱
  • @Schollii 我所做的编辑应该清楚地说明: io.open("stdin") 返回 nil 因为没有这样的文件!我也知道如果函数来自文件,我可以读取它,但这不包括 stdin 的情况。我接受了答案,因为我可以自己捕获标准输入,并将其内容复制到我以后可以参考的文件中。
  • 好的,听起来不错。

标签: debugging serialization lua introspection


【解决方案1】:

使用debug.getinfo,您可以获得sourcelinedefinedlastlinedefined。除非你真的很奇怪地格式化你的代码,否则你应该能够从这个信息中提取你的函数的完整代码。无需解析代码,只需获取正确的行集即可。

【讨论】:

  • 这个方法总不能得到指定函数的源码。例如,如果函数是通过 stdin 输入的,则源代码行显示 STDIN 或类似的东西。也许如果有办法阅读 STDIN 的历史?我实际上没有意识到有一个“lastlinedefined”,这就是为什么我认为我需要一个解析器。谢谢你帮我解决这个问题。剩下的唯一事情就是弄清楚如何获取通过 STDIN 输入的内容
【解决方案2】:

您想将字节码分解为 Lua 语句和表达式。试试http://chunkspy.luaforge.net/。或者可能是http://luadec.luaforge.net/,但我没有使用它们,所以不能提供更多信息。 Luac(Lua 编译器)也有 -l 开关,它产生可能被解析的程序集列表。然后是 lbci (bhttp://www.tecgraf.puc-rio.br/~lhf/ftp/lua/#lbci)。您可能会发现 Getting the AST of a function 很有用。最后,我建议您搜索“lua decompiler”。

【讨论】:

  • 这个解决方案在技术上可能有效,但它不能总是产生函数的原始源(尽管它给你的总是完全等价的)。一定有某种方法可以让诸如 require() 函数之类的东西自动加载 Lua 可访问内存中某处的源代码?
  • @MilesRufat-Latre 为什么 lhf 的答案对你不起作用?如果您只想要源,您可以使用定义函数源的文件和行#(使用调试模块),但这可能并不总是有效。您可能可以通过调试模块拦截 require 。也许如果您在问题中发布了一个 i/o 示例,您可以获得更多答案。
猜你喜欢
  • 1970-01-01
  • 2019-03-04
  • 2013-10-27
  • 2016-01-04
  • 1970-01-01
  • 2016-09-15
  • 2011-07-30
  • 2013-08-30
  • 2020-03-11
相关资源
最近更新 更多