Lua 没有内置的调试设施。它使用一种特殊的接口,这种接口依赖函数和 钩子(hooks)。该接口允许构造不同种类的调试器,分析器以及其他工具用以从解释器得到所需的信息。
得到解释程序运行时堆栈信息的主要函数是:
int lua_getstack (lua_State *L, int level, lua_Debug *ar);
这个函数用一个指定等级的函数的 activation record 的标示符填充一个 lua_Debug
结构,等级 0 是当前运行函数,然而等级 n+1 是在等级 n 上调用的函数。当没有错误发生时,lua_getstack
返回 1;当在比栈更深的等级上调用的时候,它返回 0;
lua_Debug
结构被用来携带一个处于活动状态的函数的各种信息:
typedef struct lua_Debug { int event; const char *name; /* (n) */ const char *namewhat; /* (n) `global', `local', `field', `method' */ const char *what; /* (S) `Lua' function, `C' function, Lua `main' */ const char *source; /* (S) */ int currentline; /* (l) */ int nups; /* (u) number of upvalues */ int linedefined; /* (S) */ char short_src[LUA_IDSIZE]; /* (S) */ /* private part */ ... } lua_Debug;
lua_getstack
只填充结构的私有部分以备之后使用。要填充 lua_Debug
其他有用信息,调用
int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
这个函数发生错误是返回 0 (举个例子,一个无效的 what
选项)。what
字符串中的每个字符选择填充一些 ar
结构的字段,把上面在 lua_Debug
定义中用圆括号括起来的字母作为指示: `S
´ 填充在 source
, linedefined
和 what
字段中;`l
´ 填充在 currentline
字段中,等等...。而且,`f
´ 将正在运?性谒燃渡系暮谷攵颜弧?
想要从一个不处于活动状态的函数那得到信息(就是不在栈上的函数),你需要将其压入栈并且用 >
´ 作为 what
字符串的开始。举个例子,要知道函数 f
定义在第几行,你需要这样写
lua_Debug ar; lua_pushstring(L, "f"); lua_gettable(L, LUA_GLOBALSINDEX); /* get global `f' */ lua_getinfo(L, ">S", &ar); printf("%d/n", ar.linedefined);
lua_Debug
的字段有如下的含义:
source
如果函数在一个字符串中定义,那么 source
就是那个字符串。如果函数定义在一个文件中,source
开始于一个 `@
´ 后面跟随文件名。 short_src
一个可打印版的 source
,用于错误信息。 linedefined
函数定义起始的行号。 what
如果这是一个Lua函数,显示 "Lua"
字符串, "C"
为C 函数,"main"
如果这是一个语句段的main部分,"tail"
如果这是一个做了尾部调用的函数。在后面的情况里,Lua 没有其他关于这个函部的信息。 currentline
代表当前函数执行到的行数。如果没有行信息可用,currentline
被设置为 -1。 name
一个所给函数合理的函数名。因为函数在Lua中属于第一类值,它们没有固定的名字:一些函数可能是多个全局变量的值,其他的可能只储存在一个表字段里。lua_getinfo
函数检测函数如何被调用或者是否为一个全局变量的值以寻找一个合适的名字。如果找不到合适的名字,name
被设置为 NULL
。 namewhat
name
字段的解释。根据函数如何被调用,namewhat
的值可以是 "global"
, "local"
, "method"
, "field"
或者 ""
(空字符串)。(当没有其他可选项的时候Lua使用空字符串代替) nups
函数上值的数量。 为了更多的操作局部变量和上值,调试接口使用索引:第一个参数或者局部变量索引为 1,以此类推,直到最后一个活动的局部变量。整个函数中的活动的上值没有特定的顺序。
下面的函数允许操作一个所给激活记录的局部变量:
const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
参数 ar
必须是一个被前一个 lua_getstack
调用填充的有效的激活记录或者作为一个钩子函数的参数(见 4.3)。lua_getlocal
获得一个局部变量的索引 n
,将变量的值压入栈,并且返回变量名。lua_setlocal
从栈顶分配一个值给变量并且返回变量名。当索引超过活动的局部变量的数量时,两个函数都返回 NULL
。
以下的函部可以操作所给函数的上值(不像局部变量,函数的上值即使在函数不处于活动状态的时候都可以被访问):
const char *lua_getupvalue (lua_State *L, int funcindex, int n); const char *lua_setupvalue (lua_State *L, int funcindex, int n);
这些函数可以作为Lua 函数使用也可以作为C 函数使用。(作为Lua 函数,上值是函数外部使用的局部变量,因此它被包含在函数闭包中。)funcindex
指向栈中的一个函数。lua_getupvalue
得到一个上值的索引 n
,将上值的值压入栈,并返回其变量名。lua_setupvalue
从栈顶分配一个值给上值并返回变量名。当索引大于上值数量时,两个函数都返回 NULL
。对于C 函数来说,这些函数使用空字符串作为所有上值的变量名。
作为一个例子,下面的函数列举了所给等级的栈中的函数的所有局部变量名和上值变量名:
int listvars (lua_State *L, int level) { lua_Debug ar; int i; const char *name; if (lua_getstack(L, level, &ar) == 0) return 0; /* failure: no such level in the stack */ i = 1; while ((name = lua_getlocal(L, &ar, i++)) != NULL) { printf("local %d %s/n", i-1, name); lua_pop(L, 1); /* remove variable value */ } lua_getinfo(L, "f", &ar); /* retrieves function */ i = 1; while ((name = lua_getupvalue(L, -1, i++)) != NULL) { printf("upvalue %d %s/n", i-1, name); lua_pop(L, 1); /* remove upvalue value */ } return 1; }
Lua offers a mechanism of hooks, which are user-defined C functions that are called during the program execution. A hook may be called in four different events: a call event, when Lua calls a function; a return event, when Lua returns from a function; a line event, when Lua starts executing a new line of code; and a count event, which happens every "count" instructions. Lua identifies these events with the following constants: LUA_HOOKCALL
, LUA_HOOKRET
(or LUA_HOOKTAILRET
, see below), LUA_HOOKLINE
, and LUA_HOOKCOUNT
.
A hook has type lua_Hook
, defined as follows:
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
You can set the hook with the following function:
int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
func
is the hook. mask
specifies on which events the hook will be called: It is formed by a disjunction of the constants LUA_MASKCALL
, LUA_MASKRET
, LUA_MASKLINE
, and LUA_MASKCOUNT
. The count
argument is only meaningful when the mask includes LUA_MASKCOUNT
. For each event, the hook is called as explained below:
count
instructions. (This event only happens while Lua is executing a Lua function.) A hook is disabled by setting mask
to zero.
You can get the current hook, the current mask, and the current count with the following functions:
lua_Hook lua_gethook (lua_State *L); int lua_gethookmask (lua_State *L); int lua_gethookcount (lua_State *L);
Whenever a hook is called, its ar
argument has its field event
set to the specific event that triggered the hook. Moreover, for line events, the field currentline
is also set. To get the value of any other field in ar
, the hook must call lua_getinfo
. For return events, event
may be LUA_HOOKRET
, the normal value, or LUA_HOOKTAILRET
. In the latter case, Lua is simulating a return from a function that did a tail call; in this case, it is useless to call lua_getinfo
.
While Lua is running a hook, it disables other calls to hooks. Therefore, if a hook calls back Lua to execute a function or a chunk, that execution occurs without any calls to hooks.