方法一:调用Lua库函数
调用Lua函数的步骤为:
- 获得函数并压入栈
- 按顺序压入参数
- 调用lua_pcall,该函数的第二个参数是参数个数,第三个参数是返回个数,第四个参数是异常处理函数
示例程序:
//c
/* call a function 'f' defined in Lua */
double f (lua_State *L, double x, double y) {
int isnum;
double z;
/* push functions and arguments */
lua_getglobal(L, "f"); /* function to be called */
lua_pushnumber(L, x); /* push 1st argument */
lua_pushnumber(L, y); /* push 2nd argument */
/* do the call (2 arguments, 1 result) */
if (lua_pcall(L, 2, 1, 0) != LUA_OK)
error(L, "error running function 'f': %s",
lua_tostring(L, -1));
/* retrieve result */
z = lua_tonumberx(L, -1, &isnum);
if (!isnum)
error(L, "function 'f' must return a number");
lua_pop(L, 1); /* pop returned value */
return z;
}
方法二:自定义一个通用的调用Lua函数方法
示例:
定义一个call_va,然后这样调用:
//c
call_va(L, "f", "dd>d", x, y, &z);
第二个参数是函数名,第三个参数是参数和返回值:字符串 “dd>d” 表示函数有两个double 类型的参数,一个double 类型的返回结果。我们使用字母 ‘d’ 表示double;’i’ 表示integer,’s’ 表示strings;’>’ 作为参数和结果的分隔符。如果函数没有返回结果,’>’ 是可选的。
call_va的定义如下:
//c
#include <stdarg.h>
void call_va (lua_State *L, const char *func,
const char *sig, ...) {
va_list vl;
int narg, nres; /* number of arguments and results */
va_start(vl, sig);
lua_getglobal(L, func); /* push function */
for (narg = 0; *sig; narg++) { /* repeat for each argument */
/* check stack space */
luaL_checkstack(L, 1, "too many arguments");
switch (*sig++) {
case 'd': /* double argument */
lua_pushnumber(L, va_arg(vl, double));
break;
case 'i': /* int argument */
lua_pushinteger(L, va_arg(vl, int));
break;
case 's': /* string argument */
lua_pushstring(L, va_arg(vl, char *));
break;
case '>': /* end of arguments */
goto endargs;
default:
error(L, "invalid option (%c)", *(sig - 1));
}
}
endargs:
nres = strlen(sig); /* number of expected results */
if (lua_pcall(L, narg, nres, 0) != 0) /* do the call */
error(L, "error calling '%s': %s", func,
lua_tostring(L, -1));
nres = -nres; /* stack index of first result */
while (*sig) { /* repeat for each result */
switch (*sig++) {
case 'd': { /* double result */
int isnum;
double n = lua_tonumberx(L, nres, &isnum);
if (!isnum)
error(L, "wrong result type");
*va_arg(vl, double *) = n;
break;
}
case 'i': { /* int result */
int isnum;
int n = lua_tointegerx(L, nres, &isnum);
if (!isnum)
error(L, "wrong result type");
*va_arg(vl, int *) = n;
break;
}
case 's': { /* string result */
const char *s = lua_tostring(L, nres);
if (s == NULL)
error(L, "wrong result type");
*va_arg(vl, const char **) = s;
break;
}
default:
error(L, "invalid option (%c)", *(sig - 1));
}
nres++;
}
va_end(vl);
}