【问题标题】:Getting all functions in a Lua script获取 Lua 脚本中的所有函数
【发布时间】:2016-09-15 13:08:23
【问题描述】:

我正在尝试找出一种方法来获取 Lua 脚本中的所有函数。这个脚本已经通过loadfile编译成一个函数。例如,我想获取下面脚本中定义的每个函数。

function example1()

end

local function example2()

end

local library = {}

function library:example3()

end

(function()
    -- Functions like this too.
end)

名称并不重要,我只是在寻找一种获取实际函数的方法,这样我就可以在 debug.getinfo 中使用它们并获取类似于它们定义的行的信息。我有 LuaJIT,如果这样的话这更容易。这样的事情甚至可能吗?提前致谢。

【问题讨论】:

    标签: function lua


    【解决方案1】:

    我猜该文件将其函数声明为全局函数,否则很容易跟踪返回的内容。

    如果是这种情况,您可以使用通用 for 循环遍历所有全局项,并且只从它们中获取函数:

    allFuncs = {}
    
    for key, item in pairs(_G) do
        if type(item) == "function" then
            allFuncs[#allFuncs + 1] = item
        end
    end
    

    _G 是保存所有全局变量的表)

    然后您将有一个列表 (allFuncs) 包含所有声明的函数,但请注意,它还将包含默认函数,如 setmetatablexpcall

    很容易修改代码以防止发生这种情况,而仅将其用于测试/学习:

    function allFuncs()
        local funcsTab = {}
        for key, item in pairs(_G) do
            if type(item) == "function" then
                funcsTab[#funcsTab + 1] = item
            end
        end
        return funcsTab
    end
    
    defaultFuncs = allFuncs()
    
    --then you load your file: other functions get declared
    --we create another table containg the default + the new functions
    
    myFuncs = allFuncs()
    
    --then you subtract the first table from the second
    
    for i = 1, #myFuncs do
        for o = 1, #defaultFuncs do
            if myFuncs[i] == defaultFuncs[o] then
                table.remove(myFuncs, i)
            end
        end
    end
    

    这是如果您的文件不返回任何内容并将其函数声明为全局函数。

    如果文件将它们声明为本地,然后返回包含它们的表,只需使用第一段代码将 _G 替换为返回的表。

    【讨论】:

    • 脚本将是动态的(它来自其他地方,用户创建),我需要获取该脚本中定义的每个函数,而不是每个全局函数。不过,谢谢!
    • 好的,但是那个脚本是如何声明函数的呢?它是否将它们声明为local,然后将它们返回到一个表中?还是只是将它们声明为全局函数,而不返回任何内容?如果它确实返回了一个表,您可以使用上面的代码将_G 替换为该返回的表。
    【解决方案2】:

    如果没有语法或字节码分析,这是不可能的,因为每个函数定义都是一个赋值(只是在您的示例中具有不同的形式)。请参阅bytecode inspector 和相关讨论here。对于语法分析,您可以使用metalua 或类似lua-loose-parser 的东西。请记住,即使这些工具也不会为您提供完整的函数列表,因为某些函数可能是使用 loadstring(或类似方法)动态定义的。

    如果您只能访问loadfile 的结果,那么最好的办法是使用字节码分析器。

    【讨论】:

      【解决方案3】:

      这可以在 LuaJIT 中使用 jit.attach

      您可以将回调附加到许多编译器事件 jit.attach。可以调用回调:

      • 函数已编译为字节码(“bc”)时;
      • 当跟踪记录开始或停止时(“trace”);
      • 正在记录轨迹(“记录”);
      • 或当跟踪通过侧出口(“texit”)退出时。

      http://wiki.luajit.org/JIT-Compiler-API#jit-attach

      jit.attach(function(f)
          local funcInfo = jit.util.funcinfo(f)
      end, "bc")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多