2012-05-31 16 views
11

W Lua, czy jest możliwe, aby wiedzieć, która funkcja nazywa obecną funkcję.Lua - dowiedzieć się funkcji wywołującej

Na przykład

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


function b() 
    a() 
end 

Czy coś takiego jest możliwe?
Czy biblioteka debugowania ma taką funkcjonalność?

Odpowiedz

17

Można użyć debug.traceback():

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


function b() 
    a() 
end 

b() 

która drukuje:

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

można użyć debug.sethook(), aby utworzyć hak, który jest wywoływana za każdym razem, pewne wydarzenia specjalne zdarzyć w Lua. może być przydatny do takich rzeczy.

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() 

to drukuje "dzwoniący1 został wywołany z caller2!"

debug.sethook może obsłużyć 3 różne znaki w drugim parametrze, dzięki czemu możesz powiadomić, kiedy należy Cię powiadomić. "c" oznacza wywołanie funkcji przechwytującej za każdym razem, gdy funkcja jest wywoływana w lua, "r" oznacza wywołanie funkcji przechwytującej za każdym razem, gdy funkcja zwraca w lua, a "l" oznacza wywołanie funkcji przechwytującej, gdy lua przetwarza nową linię kodu .

można to ustawić, aby zbudować własne niestandardowe śledzenie stosu, jeśli naprawdę chcesz, i możesz również użyć debug.getlocal() w swoim haku, aby nawet spróbować dowiedzieć się, jakie argumenty zostały przekazane do Twojej wywołanej funkcji.

edycja dla lhf. jest to w rzeczywistości o wiele prostszy sposób robienia tego, o co prosisz, jeśli nie musisz tego śledzić i musisz tylko znać kontekst, w jaki sposób wywołano tę funkcję.

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

Nie musisz wywoływać 'debug.getinfo' wewnątrz haka. Możesz bezpośrednio wywołać 'debug.getinfo' w swojej funkcji. – lhf

+1

ha, masz rację. Przeprojektowałem to. Dodam urywek pokazujący prostszy sposób. –

+1

Dzięki optymalizacji wywołania końcowego uproszczona wersja może dać nieprawidłowe wyniki, jeśli wywołanie 'caller2' wywołania' caller1' spowoduje optymalizację wywołania końcowego, ponieważ zapobiega dodawaniu do stosu wywołań. –

Powiązane problemy