2012-05-31 52 views
11

在Lua中,是否有可能知道哪个函数调用了当前函数。Lua - 找出调用函数

例如

function a() 
    get_calling_function() --Should print function b 
end 


function b() 
    a() 
end 

是这样的可能吗?
调试库是否有这样的功能?

回答

17

你可以使用debug.traceback()

function a() 
    print(debug.traceback()) 
end 


function b() 
    a() 
end 

b() 

这将打印:

 
stack traceback: 
    ./test.lua:45: in function 'a' 
    ./test.lua:50: in function 'b' 
    ./test.lua:53: in main chunk 
    [C]: in ? 
9

你可以使用debug.sethook()设置一个是被每次某些特殊事件发生在所谓的钩LUA。它可以用于这样的事情。

local debugInfo = { caller = nil, callee = nil } 
function hook() 
    local info = debug.getinfo(2) 
    if info == nil then 
     debugInfo.callee = nil 
     return 
    end 

    -- we only want to watch lua function calls (not C functions) 
    if info.what ~= "Lua" then 
     debugInfo.callee = "C function" 
     return 
    end 

    debugInfo.caller = debugInfo.callee 
    debugInfo.callee = info.name 
end 


debug.sethook(hook, "c") 

function caller1() 
    if debugInfo.caller ~= nil and debugInfo.callee ~= nil then 
     msg = debugInfo.callee.. " was called by ".. debugInfo.caller.. "!" 
     print(msg) 
    end 
end 

function caller2() 
    caller1() 
end 


caller2() 

此打印件'caller1被从呼叫者2调用!'

debug.sethook可以处理第二个参数中的3个不同的字符,所以你可以让它知道什么时候通知你。 'c'表示在lua中调用一个函数时调用你的钩子函数,'r'表示每当函数在lua中返回时调用你的钩子函数,'l'表示当lua处理一行新的代码时调用你的钩子函数。

如果你真的想要创建自己的自定义堆栈跟踪,你也可以在你的挂钩中使用debug.getlocal()甚至试图找出传递给你的被调用函数的参数。

编辑为lhf。这实际上是一种更简单的方式来执行你所问的问题,如果你不需要跟踪这些,只需要知道函数的调用方式。

function caller1() 
    local current_func = debug.getinfo(1) 
    local calling_func = debug.getinfo(2) 
    print(current_func.name.. " was called by ".. calling_func.name.. "!") 
end 

function caller2() 
    caller1() 
end 
+4

您不需要在钩子内调用'debug.getinfo'。你可以直接在函数内调用'debug.getinfo'。 – lhf

+1

哈,你说得对。我过度设计了它。我会添加一个片段显示更简单的方法。 –

+1

使用尾部调用优化,如果'caller2'调用'caller1'最终调用尾部优化,则更简单的版本可能会给出错误结果,因为它阻止了对调用堆栈的添加。 –