Oh man da ist es doch schon fast wieder 4 Monate her seit dem Letzen Post aber naja ( *das war's dann mit der Vorstellung jede Woche ein post* ), aber nun gut..
Also um was soll es im nächsten Abschnitt gehen ?
-Lua environment (env)
Was ist das ?
Nun eine Env ist der Kontext aus dem Funktionen ausgeführt werden ( normale ist es _G ).
Nun alles was man global anlegt kommt in die Env,
a = 1 ist das selbe wie _G.a = 1 ebenfalls könnte man auch durch die dafür vorgesehen Setter und getter so bekommen:getfenv( 1 ).a
im folgenden werde ich euch demonstrieren wie man funktionene hooken kann ohne die Funktion zu Detouren ( hooken bedeutet das man seine eigene Funktion zwischenschalten kann )
das erste was wir brauchen ist die Globaletabelle da wenn wir eine eigene Env anlegen es keine funktionen kennt da sie nicht bekannt sind.
im beispiel werde ich die ENV mit ev bezeichnen.
wenn man jetzt die Enviroment auf ev setzt so würde es keine fuktionen wie string oder table etc. geben da (bei der Orginalen geht das da die Zugriffe auf string etc über _G erfolgt ) sie der Env nicht bekannt sind also um dies zu verhindern gibt es 2 möglichkeiten
1. Die env auf eine Kopie von _G setzen ( so kennt sie von sich aus alle Funktionen )
2. Der env eine Refferenz auf _G geben ( so kann man z.b env.g = _G und in der env g["string"]["..."] benutzen )
Da wir das Hooking über eine Metatabelle machen werden, fällt die erste Lösung weg da wir sonst die meta Methode __index nicht benutzen können (zu Metatabellen werde ich in einem anderen post kommen).
Ich möchte klarstellen, dass das hier nur ein Proof of concept ist und ich daher dies nur mit der _G Tabelle mach und deren direkten Indexen ( also _G.print aber nicht _G.string.len ) es ist zwar möglich macht es aber nur unnötig kompliziert (im beispiel).
also zurück zum Thema wir brauchen _G für alle Funktionen die uns Lua zu verfügung stellt.
nun zur Veranschaulichung werde ich zeigen was passiert wenn wir in eine Env etwas schreiben
local ev = { g = table.Copy( _G ) , print = print , getfenv = getfenv}//ich gebe der env ein par funktionen die ich brauche
setfenv( 1 , ev) // setzen der env
a = 1 // test var
print( a ) // 1
print( ev.a ) // 1
print( getfenv(0).a ) // nil
print( getfenv(1).a ) // 1
print( _G.a ) // error _G undef
nun ich hoffe das war bis jetzt verständlich... also nun weiter wir geben unserer env eine meta Tabelle
local meta = {
__index = function( t , k ) //merke index wird nur aufgerufen wenn es in der tablle nicht vorhanden ist dies ist nicht schlimm da die env eh lehr ist
if( isfunction( ev.g[k] ) ) then // wenn funktion
ev.g.print( "_G['" .. k .. "']" )//print des namens
return function( ... ) //hier erstelle ich den hook welcher mir die Parameter anzeigt mitder die Funktion aufgerufen wird
local args = { ...}
ev.g.PrintTable( args )
return ( ev.g[k] || function() end )( ... )
end
end
return ev.g[k]// g[k] geht auch //für den fall das es keine funktion ist retrurnen wir den normalen wert
end }
Alles anzeigen
also nun haben wir die metatabelle die müssen wir noch auf unsere Env setzen hier der volle Code:
local ev = { g = table.Copy( _G ) }
local meta = {
__index = function( t , k ) //merke index wird nur aufgerufen wenn es in der tablle nicht vorhanden ist dies ist nicht schlimm da die env eh lehr ist
if( isfunction( ev.g[k] ) ) then // wenn funktion
ev.g.print( "_G['" .. k .. "']" )//print des namens
return function( ... ) //hier erstelle ich den hook welcher mir die Parameter anzeigt mitder die Funktion aufgerufen wird
local args = { ...}
ev.g.PrintTable( args )
return ( ev.g[k] || function() end )( ... )
end
end
return ev.g[k] //für den fall das es keine funktion ist retrurnen wir den normalen wert
end }
setmetatable( ev , meta )
setfenv( 1 , ev )// zurücksetzen wäre dann setfenv( 1 , ev.g) in diesem fall
print("test")
//output:
//_G['print'] <- name der funktion
//1 = test <- parameter
//test <- output
Alles anzeigen
wenn man die Env global macht ist es so super einfach für verschiedene Scripte zusammen zu arbeiten bzw. lokale weiterzugeben
ich hoffe es ist verständlich wenn nicht konstruktive Kritik gerne gesehen genauso wie fragen / Verbesserungsvorschläge.
K03