lua_pcall 函数
lua_pcall 可以执行lua代码 前面的例子中load时就执行了lua脚本或者lua编译文件
int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);
nargs: 待调用函数的参数数量
nresults: 期望的结果个数
errfunc: 处理错误函数的索引
就像 settop函数的赋值一样,lua_pcall 会根据要求的数量来调整实际参数,即压入nil或者丢弃多余的结果。压入一个结果前,lua_pcall会向删除栈中的函数以及参数。如果一个函数有多个返回值,那么第一个结果最先入栈。
如果lua_pcall在运行时有任何错误,lua_pcall会返回一个非零值,并且在栈中压入一条错误消息。不过即使如此,它仍然会弹出函数以及参数。然而,在压入错误消息前,如果存在一个错误处理函数,lua_pcall会调用它。通过lua_pcall的最后一个参数可以指定错误处理函数。0表示没有错误处理函数,那么最终的消息就是原来的错误消息。如果传入非零值,那么这个参数就应该时一个处务处理函数在栈中的索引,因此,错误处理函数必须先压入栈中,也就是必须位于待调用函数机器参数的下面,先其入栈。
对于一个普通的错误,lua_pcall返回错误代码LUA_ERRRUN。担忧两种特殊的错误情况,不会运行错误处理函数。第一种时内存分配错误,这类错误lua_pcall总是返回LUA_ERRMEM。第二类错误发生在lua运行错误处理函数时,在这种情况没有必要再次调用错误处理函数,因此lua_pcall会立即返回LUA_ERRERR
代码示例:
load_func.lua
function f (x, y)
return (x^2 * math.sin(y)) / (1-x)
end
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
#endif // __cplusplus
static void stack_dump(lua_State *L) {
int i;
int top = lua_gettop(L);//
printf("stack len:%d ", top);
for (i = 1; i <= top; i++) {
int t = lua_type(L, i);
switch (t) {
case LUA_TSTRING: {
printf("'%s'", lua_tostring(L, i));
break;
}
case LUA_TBOOLEAN: {
printf(lua_toboolean(L, i) ? "true" : "false");
break;
}
case LUA_TNUMBER: {
printf("%g", lua_tonumber(L, i));
break;
}
default:
printf("%s", lua_typename(L, t));
break;
}
printf(" ");
}
printf("\n");
}
void error(lua_State *L, const char* fmt, ...) {
va_list argp;
va_start(argp, fmt);
vfprintf(stderr, fmt, argp);
va_end(argp);
lua_close(L);
exit(EXIT_FAILURE);
}
double f(lua_State* L, double x, double y) {
double z;
//压入函数和参数
lua_getglobal(L, "f"); //待调用的函数
lua_pushnumber(L, x); //压入第一个参数
lua_pushnumber(L, y); //压入第二个参数
stack_dump(L);
//完成调用 (2个参数 1个结果) 执行之后,压入的变量会被弹出
if (lua_pcall(L, 2, 1, 0) != 0) {
error(L, "error running function 'f' :%s \n", lua_tostring(L, -1));
}
stack_dump(L);
//检索结果
if (!lua_isnumber(L, -1)) {
error(L, "error running function 'f' must return a number :%s \n", lua_tostring(L, -1));
}
z = lua_tonumber(L, -1);// 弹出结果
lua_pop(L, 1); //把结果 以及压入的函数和参数弹出
stack_dump(L);
return z;
}
void load(lua_State* L, const char* fname) {
if (luaL_loadfile(L, fname) || lua_pcall(L, 0, 0, 0)) {
//luaL_loadfile\lua_pcall 发生错误,两个函数都会把错误消息压入栈,并返回一个非零的错误代码,可以通过lua_tostring获得错误信息
error(L, "error cannot run config file:%s\n", lua_tostring(L, -1));
}
}
int main() {
lua_State* L = luaL_newstate();
luaL_openlibs(L); //打开标准库 lualib.h
load(L, "./load_func.lua");
double x = 2.5f;
double y = 3.0f;
double z = 0.0f;
z = f(L, x, y);
printf("function f result is %g \n", z);
lua_close(L);
system("pause");
}