问题描述:

写一个函数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
			print('  arg:'..i,'',name)
	debug.sethook(hook, "c")
	fun()
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]: ?
  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
			print('  arg:'..i,'',name)
	debug.sethook(hook, "c")
	pcall(fun)
end
结果: 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
		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
			i = i+1
	pcall(find)

测试结果我就不唠叨了,如果只是简单的参数检测,大家可以参考一下上面的,不说了,显然这还不是我想要的,继续研究。。。。

好消息,经过不断的努力,研究,终于搞出来一个终极版本,犹豫前面两天写了那么多,现在先来回顾一下:

在lua中获取一个lua函数的行参.

local d = 8

function func(a,b,c)

d = 9

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
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
			args[i] = name
	debug.sethook(hook, "c")
	pcall(fun)
	return unpack(args)
print(getArgs(loadstring([[return function (a,b,v)
	local oo = 9
	print(oo)
end]])()))
print(getArgs(fun))
print(xxx)
a	b	v

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

cwd,lua.exe的当前目录 stopOnEntry,开始调试时是否先暂停 luaexe,指定lua exe的路径,如果不填则由luaVersion和luaArch决定 luaVersion,指定lua时的版本。可选项有5.1 / 5.2 / 5.3 / 5.4。 luaArch,指定lua时的指令集,仅Windows有效。可选项有x86 / x86_64。 path,用于初始化package.path cpath,用于初始化package.cpath arg0,lua.exe的命令数,用于初始化arg的arg [-n] .. arg [0] arg,lua.exe的命令数,用于初始化arg的arg [1] .. arg [n] consoleCoding,lua的标准输出的编码,交替utf8,ansi,none,等于non 随着对Lua使用的增加,开始关注很多该语言的细节,例如,怎样向Lua函数传递不同种类、不同数量的数,怎样返回多种数等等。今天主要介绍Lua函数的基本用法,包括可变数的使用。 1. Lua函数格式 Lua函数定义格式如下: optional_function_scope function function_name( argument1, argument2, argument3..., argumentn) function_body return result_params_   getinfo是调试Lua程序时一个很重要很常见的函数,主要用于获取函数调用的基本信息。这个函数的难点在于各个数的含义。下面一一介绍。 一、函数简介: 1.原型:getinfo(level, arg) 2.调用:debug.getinfo(level, arg) 3.返回值:返回一个包含函数信息的table,table的内容由数arg决定,包含哪个函数的信息由level决定. 调用select时,必须传入一个固定的实selector(选择开关)和一系列数。如果selector为数字n,那么select返回列表中从索引n开始到结束的所有列表,否则只能为字符串。Lua函数可以接收可变数目的数,和C语言类似,在函数列表中使用三点。同时我们可以将可变数赋值给一个变量。,这样select返回变长数的总数。表示函数有可变的数。输出结果与上述一样。 最近想做个工具来做一些lua代码检测,比如统计某函数体里的a函数的调用次数,调用绑定事件后是否有把其返回值在某退出函数里解绑定,或者某函数调用的数是不是和协议文档里的有对应上(这个还是建议直接从协议文档生成lua代码的好).大学时就用正则表达式做过java代码的解析了,这次想换个实现姿势,也想弄个通用点的,大致想法就是提取lua代码中的函数体和表达式信息,并转化成一些字符串列表方便查询。比如把一...