lua用debug获取函数的行参列表

问题描述:

   写一个函数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


大家有兴趣自己研究一下原因,又问题可以提问,欢迎大家交流指正.



  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值