lua_pcall() 函数是 C API 接口,用来和 lua 进行交互的函数,其原型为:
int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);
nargs: 表示参数个数,即你向栈中压入的参数个数。
nresults: 返回值个数,如果有返回值,则 lua 会按这个数量将返回值压入栈中。
msgh: 如果是 0 则表示要调用的函数如果出错了,则出错信息返回压入栈顶,非 0 时,则表示处理出错的函数在栈中的 index。
返回值:
/* thread status */
#define LUA_OK 0
#define LUA_YIELD 1
#define LUA_ERRRUN 2
#define LUA_ERRSYNTAX 3
#define LUA_ERRMEM 4
#define LUA_ERRERR 5
有如下代码,需要调用 lua 里的 parseData 函数,但这个函数里有一个错误,即:COM.lua_func(12, 23, 45); 因为没给 lua_func 赋过值,所以这里调用会失败。调用 lua 里的语句如果出错,则哪里出错就从哪里返回了。
我们先看最后一个lua_pcall() 最后一个参数是 0 的情况:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
}
#endif
/* 将要注册给Lua 的函数, 定义Lua 传回三个数值 */
int LuaFunc(lua_State *L)
{
if(lua_gettop(L) != 3)
{
printf("lua send back para is not correct.\n");
return 1;
}
int ret1 = (int)lua_tonumber(L, -3);
int ret2 = (int)lua_tonumber(L, -2);
int ret3 = (int)lua_tonumber(L, -1);
printf("Line: %d, Lua send back %d, %d, %d\n", __LINE__, ret1, ret2, ret3);
return 0;
}
int errFunc(lua_State* L)
{
printf("error handler, top type = %d\n", lua_type(L, -1));
char buf[128] = {0};
if(LUA_TSTRING == lua_type(L, -1))
{
memcpy(buf, lua_tostring(L, -1), sizeof(buf));
printf("get error from lua: %s\n", buf);
}
}
int main()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
if(luaL_loadfile(L, "parse.lua"))
{
printf("load file: parse.lua faild...\n");
lua_close(L);
return 1;
}
lua_pcall(L, 0, 0, 0); /* 前面这几步都基本固定 */
lua_getglobal(L, "COM"); /* 先找到表 */
if(lua_type(L, -1) != LUA_TTABLE)
{
printf("can not find table: COM \n");
lua_close(L);
return 1;
}
// lua_pushstring(L, "lua_func"); /* 注册函数 */
// lua_pushcfunction(L, LuaFunc); /* 往表 COM 里设置了COM[key] = value, 即 COM["lua_func"] = LuaFunc */
// lua_settable(L, -3);
lua_getglobal(L, "parseData");
if(lua_type(L, -1) != LUA_TFUNCTION)
{
printf("can not find function: parseData.\n");
lua_close(L);
return 1;
}
lua_pushstring(L, "C Call Lua function");
int ret = lua_pcall(L, 1, 0, 0);
printf("ret = %d, top type: %d\n", ret, lua_type(L, -1));
char errStr[128] = {0};
memcpy(errStr, lua_tostring(L, -1), sizeof(errStr));
printf("get err: %s\n", errStr);
lua_close(L);
return 0;
}
--定义了一个全局表
COM = {}
function parseData(str)
print("From c/c++ str: "..str);
COM.lua_func(12, 23, 45);
COM.lua_var = "changed in lua";
end
出错时,直接从栈顶获取出错信息。如果要添加出错处理函数呢,该怎么处理呢?如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
}
#endif
/* 将要注册给Lua 的函数, 定义Lua 传回三个数值 */
int LuaFunc(lua_State *L)
{
if(lua_gettop(L) != 3)
{
printf("lua send back para is not correct.\n");
return 1;
}
int ret1 = (int)lua_tonumber(L, -3);
int ret2 = (int)lua_tonumber(L, -2);
int ret3 = (int)lua_tonumber(L, -1);
printf("Line: %d, Lua send back %d, %d, %d\n", __LINE__, ret1, ret2, ret3);
return 0;
}
int errFunc(lua_State* L)
{
printf("error handler, top type = %d\n", lua_type(L, -1));
char buf[128] = {0};
if(LUA_TSTRING == lua_type(L, -1))
{
memcpy(buf, lua_tostring(L, -1), sizeof(buf));
printf("get error from lua: %s\n", buf);
}
}
int main()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
if(luaL_loadfile(L, "parse.lua"))
{
printf("load file: parse.lua faild...\n");
lua_close(L);
return 1;
}
lua_pcall(L, 0, 0, 0); /* 前面这几步都基本固定 */
lua_pushcfunction(L, errFunc);
lua_getglobal(L, "COM"); /* 先找到表 */
if(lua_type(L, -1) != LUA_TTABLE)
{
printf("can not find table: COM \n");
lua_close(L);
return 1;
}
// lua_pushstring(L, "lua_func"); /* 注册函数 */
// lua_pushcfunction(L, LuaFunc); /* 往表 COM 里设置了COM[key] = value, 即 COM["lua_func"] = LuaFunc */
// lua_settable(L, -3);
lua_getglobal(L, "parseData");
if(lua_type(L, -1) != LUA_TFUNCTION)
{
printf("can not find function: parseData.\n");
lua_close(L);
return 1;
}
lua_pushstring(L, "C Call Lua function");
int ret = lua_pcall(L, 1, 0, -4);
printf("ret = %d, top type: %d\n", ret, lua_type(L, -1));
lua_close(L);
return 0;
}
代码中两处不一样:1)添加处理函数:lua_pushcfunction(L, errFunc); 2)lua_pcall 函数指定处理函数在栈中的 index = -4,这里为什么是 -4 呢?因为这个函数是最先入栈的,然后是 “COM” 的值,接着是 “parseData” 的值,最后是参数 “C Call Lua function”,所以从栈顶开始它是 -4 的位置,其执行结果为: