当前位置: 首页 > 工具软件 > Lua Fun > 使用案例 >

lua 反射

宗冷勋
2023-12-01

lua 反射

      

debug实现反射功能:获取函数信息、函数局部变量、函数使用的外部局部变量等

      

             

                                

函数信息

         

getinfo(thread, f, what):获取函数的表信息

Returns a table with information about a function. You can give the 
function directly or you can give a number as the value of f, which 
means the function running at level f of the call stack of the given 
thread: level 0 is the current function (getinfo itself); level 1 is 
the function that called getinfo (except for tail calls, which do not 
count in the stack); and so on. If f is a number greater than the 
number of active functions, then getinfo returns fail.
* 以表的形式返回函数的信息
* f可以直接指定为函数、函数的栈
* f=0:getinfo函数
* f=1:调用getinfo的函数fun
* f=2:调用fun的函数
* 如果没有函数信息,返回nil
* 说明:f从0往上表示调用该函数的函数,不能向下(该函数调用的函数)

The returned table can contain all the fields returned by lua_getinfo, 
with the string what describing which fields to fill in. The default 
for what is to get all information available, except the table of 
valid lines. If present, the option 'f' adds a field named func with 
the function itself. If present, the option 'L' adds a field named 
activelines with the table of valid lines.
* 默认会返回所有函数的信息
* what=f:表中添加字段func,value为函数自己
* what=L:表中添加字段activelines,表示函数的有效行(排除空行、只包含注释的行)

For instance, the expression debug.getinfo(1,"n").name returns a name 
for the current function, if a reasonable name can be found, and the 
expression debug.getinfo(print) returns a table with all available 
information about the print function
* debug.getinfo(1,"n").name:返回表中name对应的值(函数的名字)
* debug.getinfo(print):返回print函数的表信息

        

示例

huli@hudeMacBook-Pro lua % cat f.lua
function fun()
  for key,value in pairs(debug.getinfo(0)) do print(key,value) end
  print()

  for key,value in pairs(debug.getinfo(1)) do print(key,value) end
  print()

  for key,value in pairs(debug.getinfo(2)) do print(key,value) end
end

fun()


-- 运行脚本
huli@hudeMacBook-Pro lua % lua f.lua
name	getinfo  --函数的名称
ntransfer	0
source	=[C]     --函数定义的位置:定义在字符串中(如c函数)、文件中(以@开头的文件)
namewhat	field
currentline	-1
func	function: 0x10ebb9d20
istailcall	false
ftransfer	0
short_src	[C]
lastlinedefined	-1
linedefined	-1
nparams	0         --函数参数的个数
isvararg	true  --函数参数是否可变
what	C         --函数的类型:可为C、lua、main
nups	0         --函数使用的外部局部变量(upvalue)的个数

name	fun       --调用getinfo的函数名称
ntransfer	0
source	@f.lua    --fun函数定义在文件中(f.lua)
namewhat	global
currentline	5
func	function: 0x600001620cf0
istailcall	false
ftransfer	0
short_src	f.lua
lastlinedefined	9
linedefined	1
nparams	0
isvararg	false
what	Lua
nups	1

ntransfer	0
source	@f.lua
namewhat	
currentline	11
func	function: 0x600001620c60
istailcall	false
ftransfer	0
short_src	f.lua
lastlinedefined	0
linedefined	0
nparams	0
isvararg	true
what	main
nups	1

        

            

                                

局部变量

         

debug.getlocal([thread,] f, local):获取函数内部设置的局部变量、调用该函数的函数的局部变量

This function returns the name and the value of the local 
variable with index local of the function at level f of the 
stack. This function accesses not only explicit local variables, 
but also parameters and temporary values.
* 返回索引为local的局部变量的name、value
* 该函数可获取局部变量、参数、临时变量
 
The first parameter or local variable has index 1, and so on, 
following the order that they are declared in the code, counting 
only the variables that are active in the current scope of the function. 
* 第一个局部变量的索引为1,按照申明顺序依次索引
* 只统计在当前作用域内有效的局部变量
 
Compile-time constants may not appear in this listing, if they were 
optimized away by the compiler. Negative indices refer to vararg arguments; 
-1 is the first vararg argument. 
* 负数表示参数:-1表示第一个参数
 
The function returns fail if there is no variable with the given index, 
and raises an error when called with a level out of range. (You can call 
debug.getinfo to check whether the level is valid.)
* 如果没有对应的局部变量,会报错
 
Variable names starting with '(' (open parenthesis) represent variables with no 
known names (internal variables such as loop control variables, and variables from 
chunks saved without debug information).
* 以"("开头的变量名表示没有显示的名称
 
The parameter f may also be a function. In that case, getlocal returns only the 
name of function parameters. 
* f可以是函数,表示获取指定函数的参数

        

debug.setlocal([thread,] level, local, value):设置函数的局部变量

This function assigns the value value to the local variable with 
index local of the function at level level of the stack. 
* 设置函数的局部变量,index是索引、level是函数所在的栈层次

The function returns fail if there is no local variable with the 
given index, and raises an error when called with a level out of range. 
You can call getinfo to check whether the level is valid. 
* 如果没有局部变量,函数返回fail,
* 如果level超出有效范围,会抛出异常

Otherwise, it returns the name of the local variable
* 如果正常设置,会返回局部变量的名称

         

示例:主函数中修改局部变量

huli@hudeMacBook-Pro lua % cat f3.lua
local a=0
local b=0

print("主函数局部变量debug前")
print("a",a)
print("b",b)

debug.setlocal(1,1,1)
debug.setlocal(1,2,2)

print("\n主函数局部变量debug后")
print("a",a)
print("b",b)


-- 执行脚本
huli@hudeMacBook-Pro lua % lua f3.lua
主函数局部变量debug前
a	0
b	0

主函数局部变量debug后
a	1
b	2

              

示例:在函数fun中get、set函数内、函数外的局部变量

huli@hudeMacBook-Pro lua % cat f2.lua
local a=0
local b=0

print("主函数局部变量debug前")
print('a',a)
print('b',b)

function fun()
  local i=0
  local j=0

  print("\n函数局部变量debug前")
  print("debug.getlocal(1,1)", debug.getlocal(1, 1))
  print("debug.getlocal(1,2)", debug.getlocal(1, 2))
  
  debug.setlocal(1,1,1)    --设置1层(fun函数)的局部变量,index=1的局部变量值为4
  debug.setlocal(1,2,2)    --设置1层(fun函数)的局部变量,index=1的局部变量值为4
  debug.setlocal(2,1,3)    --设置2层(调用fun函数的main函数)的局部变量,index=1的局部变量值为4
  debug.setlocal(2,2,4)    --设置2层调用fun函数的main函数)的局部变量,index=2的局部变量值为4

  print("\n函数局部变量debug后:")
  print("debug.getlocal(1,1)", debug.getlocal(1,1))
  print("debug.getlocal(1,2)", debug.getlocal(1,2))
end

print()
--print(debug.setlocal(2,1,1))
--print(debug.setlocal(2,2,2))

fun()

print("\n主函数局部变量debug后")
print("a",a)
print("b",b)


-- 执行脚本
huli@hudeMacBook-Pro lua % lua f2.lua
主函数局部变量debug前
a	0
b	0


函数局部变量debug前
debug.getlocal(1,1)	i	0
debug.getlocal(1,2)	j	0

函数局部变量debug后:
debug.getlocal(1,1)	i	1
debug.getlocal(1,2)	j	2

主函数局部变量debug后
a	3
b	4

               

                                  

                                

upvalue

         

getupvalue(f, up):返回指定函数f、索引为up的upvalue的name、value

This function returns the name and the value of the 
upvalue with index up of the function f. The function 
returns fail if there is no upvalue with the given index.
* 返回指定函数f的索引为up的upvalue(外部变量)的name、value
* 如果没有返回nil
 
For Lua functions, upvalues are the external local variables 
that the function uses, and that are consequently included 
in its closure.
* 如果是lua函数,upvalues是函数使用的外部局部变量
 
For C functions, this function uses the empty string "" 
as a name for all upvalues.
* 如果是c函数,所有upvalue的name都是""
 
Variable name '?' (interrogation mark) represents variables 
with no known names (variables from chunks saved without 
debug information). 
* ?表示变量没有显示的名称

         

setupvalue(f, up, value):设置函数f、索引为up的值为value

This function assigns the value value to the upvalue with index up of the 
function f. The function returns fail if there is no upvalue with the given 
index. Otherwise, it returns the name of the upvalue. 
* 设置函数f、索引up的upvalue的值为value,设置成功返回该局部变量的name
* 如果没有该变量,返回nil

           

示例

huli@hudeMacBook-Pro lua % cat f4.lua
local a=0
local b=0

function fun()
  a=a+1
  b=b+1
end

print("调用setupvalue前")
print(debug.getupvalue(fun,1))
print(debug.getupvalue(fun,2))

debug.setupvalue(fun,1,10)
debug.setupvalue(fun,2,20)

print("\n调用setupvalue后")
print(debug.getupvalue(fun,1))
print(debug.getupvalue(fun,2))


-- 执行脚本
huli@hudeMacBook-Pro lua % lua f4.lua
调用setupvalue前
a	0
b	0

调用setupvalue后
a	10
b	20

        

示例

huli@hudeMacBook-Pro lua % cat f5.lua
local a=0
local b=0

function fun()
  local i=0
  local j=0
  
  print(debug.getlocal(1,1,1))
  print(debug.getlocal(1,1,2))

  a=a+1
  b=b+1

  print(debug.getupvalue(fun,2))
  print(debug.getupvalue(fun,3))
end

print("调用setupvalue前")
fun()

print("\n调用setupvalue")
print(debug.setupvalue(fun,2,10))
print(debug.setupvalue(fun,3,20))

print("\n调用setupvalue后")
fun()

print("\n主函数调用getupvalue")
print(debug.getupvalue(fun,2))
print(debug.getupvalue(fun,3))


-- 执行脚本
huli@hudeMacBook-Pro lua % lua f5.lua
调用setupvalue前
i	0
i	0
a	1
b	1

调用setupvalue
a
b

调用setupvalue后
i	0
i	0
a	11
b	21

主函数调用getupvalue
a	11
b	21

      

            

                                

协程

         

debug可以将其他协程作为入参,调试其他协程

示例

huli@hudeMacBook-Pro lua % cat f6.lua
co = coroutine.create(
       function()
         local i=0
         print(debug.getlocal(co,1,1))
         error("错误函数")
       end
)

coroutine.resume(co)
print(debug.traceback(co))


-- 执行脚本
huli@hudeMacBook-Pro lua % lua f6.lua
i	0
stack traceback:
	[C]: in function 'error'
	f6.lua:5: in function <f6.lua:2>

       

             

                                

钩子函数

         

钩子函数:发生指定的事件(call、return、line、count)时触发调用

call:函数被调用时出发

return:函数返回时出发

line:函数新的一行执行时触发

count:函数执行完指定数量(count)指令后触发

         

gethook([thread]):获取钩子函数

Returns the current hook settings of the thread, as three values: 
the current hook function, the current hook mask, and the current 
hook count, as set by the debug.sethook function.
* 返回当前线程的钩子函数,共有3个返回值:钩子函数、mask、count
* 这些参数是sethook设置的

Returns fail if there is no active hook
* 如果没有钩子函数,返回失败

        

sethook([thread,] hook, mask, count):设置钩子函数

Sets the given function as the debug hook. 
* 将指定的函数设置为钩子函数

The string mask and the number count describe when the hook 
will be called. The string mask may have any combination of 
the following characters, with the given meaning:
    'c': the hook is called every time Lua calls a function;
    'r': the hook is called every time Lua returns from a function;
    'l': the hook is called every time Lua enters a new line of code.
* mask、count值设置
* c:每次调用函数的时候触发
* r:每次返回的时候触发
* l:每次执行新的一行时触发

Moreover, with a count different from zero, the hook is called also 
after every count instructions.
* count大于0时,每执行count次指令时触发

When called without arguments, debug.sethook turns off the hook.
* sethook不携带参数时,会关闭钩子函数

When the hook is called, its first parameter is a string describing 
the event that has triggered its call: "call", "tail call", "return", 
"line", and "count". For line events, the hook also gets the new line 
number as its second parameter. Inside a hook, you can call getinfo 
with level 2 to get more information about the running function. 
(Level 0 is the getinfo function, and level 1 is the hook function.) 
* 当钩子函数触发时,第一个参数是描述触发钩子函数的事件(call、return、line、count)
* line事件还有第2个参数:新的行号
* 在钩子函数内,还可以使用getinfo(level=2 )获取正在运行的函数信息

        

示例

huli@hudeMacBook-Pro lua % cat f8.lua
function fun()
  print('fun函数被调用了')
end

debug.sethook(fun,'c')

print("\n主函数调用fun")
fun()


-- 执行脚本
huli@hudeMacBook-Pro lua % lua f8.lua
fun函数被调用了

主函数调用fun
fun函数被调用了
fun函数被调用了
fun函数被调用了

       

                  

 类似资料: