2012-05-31 8 views
11

Luaでは、どの関数が現在の関数を呼び出したのか知ることは可能ですか?Lua - 呼び出し関数を調べる

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


function b() 
    a() 
end 

例えば

は、この可能性のようなものですか?
デバッグライブラリにはこのような機能がありますか?

あなたが debug.traceback()を使用することができ

答えて

17

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を使用することができますルアそれはこのようなものに役立つことがあります。

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がcaller2から呼び出されました!」というメッセージが表示されます。

debug.sethookは、2つ目のパラメータで3つの異なる文字を処理できるため、いつ通知するかを知らせることができます。 'c'は関数がluaで呼び出されるたびにフック関数を呼び出すことを意味し、 'r'は関数がluaで復帰するたびにフック関数を呼び出すことを意味し、 'l'はluaが新しいコード行を処理するたびに。

あなたが本当にしたい場合は、独自のカスタムスタックトレースを構築するためにこれを設定することができます。また、あなたの呼び出し内でdebug.getlocal()を使用して、呼び出された関数に渡された引数を調べることさえできます。

編集for 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

ha、そうです。私はそれをオーバーエンジニアリングしました。簡単な方法を示すスニペットを追加します。 –

+1

テールコールの最適化では、 'caller2'の' caller1'への呼び出しがテールコールの最適化を終了した場合、呼び出しスタックへの追加を防ぐので、単純なバージョンでは不正な結果が得られる可能性があります。 –

関連する問題