关于lua5.2中lua.c的一些疑惑
lua吧
全部回复
仅看楼主
level 1
int main (int argc, char **argv) {
int status, result;
lua_State *L = luaL_newstate(); /* create state */
if (L == NULL) {
l_message(argv[0], "cannot create state: not enough memory");
return EXIT_FAILURE;
}
/* call 'pmain' in protected mode */
lua_pushcfunction(L, &pmain);
lua_pushinteger(L, argc); /* 1st argument */
lua_pushlightuserdata(L, argv); /* 2nd argument */
status = lua_pcall(L, 2, 1, 0);
result = lua_toboolean(L, -1); /* get result */
finalreport(L, status);
lua_close(L);
return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
}
根据lua在线手册对lua_pcall的描述: Calls a function in protected mode.
Both nargs and nresults have the same meaning as in lua_call. If there are no errors during the call, lua_pcall behaves exactly like lua_call. However, if there is any error, lua_pcall catches it, pushes a single value on the stack (the error message), and returns an error code. Like lua_call, lua_pcall always removes the function and its arguments from the stack.
If errfunc is 0, then the error message returned on the stack is exactly the original error message. Otherwise, errfunc is the stack index of an error handler function. (In the current implementation, this index cannot be a pseudo-index.) In case of runtime errors, this function will be called with the error message and its return value will be the message returned on the stack by lua_pcall.
Typically, the error handler function is used to add more debug information to the error message, such as a stack traceback. Such information cannot be gathered after the return of lua_pcall, since by then the stack has unwound.
The lua_pcall function returns 0 in case of success or one of the following error codes (defined in lua.h):
•LUA_ERRRUN: a runtime error.
•LUA_ERRMEM: memory allocation error. For such errors, Lua does not call the error handler function.
•LUA_ERRERR: error while running the error handler function.
得知lua_pcall是可以失败的,如失败返回错误代码并在栈上压入错误信息,可为什么lua.c中为什么不检查错误代码,不管对错的调用lua_toboolean来获取pmain的返回值? 然后再调用失败报告函数。平行的使用toboolean和tostring去访问栈-1处,5.2这么写代码的用意是什么? 与5.1不同呀。
static int pmain (lua_State *L) {
int argc = (int)lua_tointeger(L, 1);
char **argv = (char **)lua_touserdata(L, 2);
int script;
int args[num_has];
args[has_i] = args[has_v] = args[has_e] = args[has_E] = 0;
if (argv[0] && argv[0][0]) progname = argv[0];
script = collectargs(argv, args);
if (script < 0) { /* invalid arg? */
print_usage(argv[-script]);
return 0;
}
if (args[has_v]) print_version();
if (args[has_E]) { /* option '-E'? */
lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */
lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
}
/* open standard libraries */
luaL_checkversion(L);
lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */
luaL_openlibs(L); /* open libraries */
lua_gc(L, LUA_GCRESTART, 0);
if (!args[has_E] && handle_luainit(L) != LUA_OK)
return 0; /* error running LUA_INIT */
/* execute arguments -e and -l */
if (!runargs(L, argv, (script > 0) ? script : argc)) return 0;
/* execute main script (if there is one) */
if (script && handle_script(L, argv, script) != LUA_OK) return 0;
if (args[has_i]) /* -i option? */
dotty(L);
else if (script == 0 && !args[has_e] && !args[has_v]) { /* no arguments? */
if (lua_stdin_is_tty()) {
print_version();
dotty(L);
}
else dofile(L, NULL); /* executes stdin as a file */
}
lua_pushboolean(L, 1); /* signal no errors */
return 1;
}
之前理解lua_CFunction型的函数,返回的是一个数量,而真正的返回值保存在栈上,可pmain的代码却是执行成功返回1个值,执行失败却没有返回值,那这让调用者多尴尬呀? main中还有toboolean在等着呢。 代码成功则压入true,失败则压入false,而pmain一直返回1,不是该这么理解吗? 看了5.2的lua.c我被颠覆了。还请前辈高人赐教,
正确的
理解。
2014年12月23日 16点12分 1
level 8
[冷]英文和中文都看不懂
2014年12月24日 04点12分 2
level 8
等等让我整理一下思路,
status = lua_pcall(L, 2, 1, 0);
result = lua_toboolean(L, -1); /* get result */
finalreport(L, status);
lua_close(L);
return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
如果pmain函数执行成功,
lua_pcall 不会在栈压入错误信息,
但是pmain会在栈压入true?
对不?
现在栈就增加一个量。
如果pmain函数执行失败,
lua_pcall 会在栈压入错误信息,
但是pmain不会在栈压入true,返回0.
对不?
现在栈就增加一个量。
所以不管成功或失败栈都是增加一个量。
2014年12月24日 09点12分 3
level 8
至于这一句
result = lua_toboolean(L, -1); /* get result */,
不是看pmain是否成功,而是看整个程序是否成功,就像上面说的,不管pmain是否成功都会在栈里增加一个量,(true或者错误信息string)
所以result = lua_toboolean(L, -1); /* get result */ 都会返回1
但是如果程序出错 lua_pcall(L, 2, 1, 0)执行不成功(c代码错误),既没有压入错误信息,也没有执行pmain函数,或者lua的堆栈内部错误 result = lua_toboolean(L, -1); /* get result */ 就可能不是返回1.
2014年12月24日 09点12分 4
level 8
这三句:
status = lua_pcall(L, 2, 1, 0);
result = lua_toboolean(L, -1); /* get result */
finalreport(L, status);
调用 finalreport函数,在下面
static void finalreport (lua_State *L, int status) {
if (status != LUA_OK) {
const char *msg = (lua_type(L, -1) == LUA_TSTRING) ? lua_tostring(L, -1)
: NULL;
if (msg == NULL) msg = "(error object is not a string)";
l_message(progname, msg);
lua_pop(L, 1);
}
}
也就是说,status是1,pcall不成功的话,它还是会在 lua_tostring(L, -1)获取错误的,用
l_message(progname, msg);
输出错误
2014年12月24日 09点12分 5
level 8
以上
2014年12月24日 09点12分 6
1