问题描述:
写一个函数getArgs(func)返回函数func的行参列表
思路是:利用lua的debug库,有一个debug.sethook(hook)函数,在注册的hook函数里面去获取参数列表,于是有了下面的代码:
function getArgs(fun)
local hook = function( ... )
local info = debug.getinfo(2)
if not info.name then return end
print('args')
for i = 1, math.huge do
local name, value = debug.getlocal(2, i)
if name == '(*temporary)' or not name then
debug.sethook()
return
end
print(' arg:'..i,'',name)
end
end
debug.sethook(hook, "c")
fun()
end
getArgs(table.clone)
结果:
lua: E:\install\lua\5.1\lua\table_ext.lua:91: bad argument #1 to 'pairs' (table expected, got nil)
stack traceback:
[C]: in function 'pairs'
E:\install\lua\5.1\lua\table_ext.lua:91: in function 'fun'
G:\myprojects\inject\showArgs.lua:50: in function 'getArgs'
G:\myprojects\inject\showArgs.lua:53: in main chunk
[C]: ?
args
arg:1 t
arg:2 nometa
结果是出来了,但是不太友好,因为table.clone()无参调用会报异常。
显然这样是不能的,那么接下来想到了lua中有一个叫pcall的函数,可以安全的调用其它函数,若果被调用的函数发生异常不会抛给用户,而是返回一个boolean,太好了,我们来试试 :
function getArgs(fun)
local hook = function( ... )
local info = debug.getinfo(3)
if info.name ~= 'pcall' then return end
print('args')
for i = 1, math.huge do
local name, value = debug.getlocal(2, i)
if name == '(*temporary)' or not name then
debug.sethook()
return
end
print(' arg:'..i,'',name)
end
end
debug.sethook(hook, "c")
pcall(fun)
end
结果:
args
arg:1 t
arg:2 nometa
两段代码差不多,大家可以自己理解一下。
结果好像是这么个意思,但是这还不是罪理想的状态,比如:我只想检测func(a,b,c)的行参列表,但是,我不想运行它,因为运行会导致整个程序不协调,好吧,上面的实现思路是行不通了。
暂时想到这么多,欢迎大家提供思路,待续。。。
时过一天,我们继续完善,昨天想了一个比较不靠谱的方案,但却是能解决上面的疑问,一开始我是拒绝这么实现的,但是因为能力水平有限,我还是这么duang~~~了,大家可以看下:
function getArgs(func)
local find = function( ... )
local info = debug.getinfo(func)
print(info)
if info.source == '=[C]' then
print('this is a C function no more message')
return
end
local i = 1
for line in io.lines(info.source:sub(2,-1)) do
if i == info.linedefined then
local s, _ = line:find('function')
local s1, _ = line:find('[(]',s)
local s2, _ = line:find('[)]',s)
print('args:('..line:sub(s1+1,s2-1)..')')
return
end
i = i+1
end
end
pcall(find)
end
测试结果我就不唠叨了,如果只是简单的参数检测,大家可以参考一下上面的,不说了,显然这还不是我想要的,继续研究。。。。
好消息,经过不断的努力,研究,终于搞出来一个终极版本,犹豫前面两天写了那么多,现在先来回顾一下:
需求:
在lua中获取一个lua函数的行参.
local d = 8
function func(a,b,c)
d = 9
end
print(getArgs(func),d)
结果:--a,b,c,8好的,一切就绪,上代码:
<pre name="code" class="javascript">local xxx = 5
function fun(a,b)
local x = 1
x = 5
xxx = 4
end
function getArgs(fun)
local args = {}
local hook = function( ... )
local info = debug.getinfo(3)
if info.name ~= 'pcall' then return end
for i = 1, math.huge do
local name, value = debug.getlocal(2, i)
if name == '(*temporary)' or not name then
debug.sethook()
error('')
return
end
args[i] = name
end
end
debug.sethook(hook, "c")
pcall(fun)
return unpack(args)
end
print(getArgs(loadstring([[return function (a,b,v)
local oo = 9
print(oo)
end]])()))
print(getArgs(fun))
print(xxx)
结果:
a b v
a b
5
大家有兴趣自己研究一下原因,又问题可以提问,欢迎大家交流指正.