一个通用的调用函数
下例是一个更高级的示例,我们将编写一个调用 Lua 函数的包装程序,其中用到了 C 语言的 stdarg 的机制。这个包装函数名为 call_va, 它接受一个待调用的全局函数的名字,一个描述参数类型和结果类型的字符串、参数列表、以及存放结果的一组指向变量的指针。函数 call_va 会处理有关 API 的所有细节。
#include <stdarg.h>
void call_va(lua_State *L, const char *func, const char *sig, ...) {
va_list vl;
int narg, nres;
va_start(vl, sig);
lua_getglobal(L, func);
for(narg = 0; *sig; narg++) {
luaL_checkstack(L, 1, "too many arguments");
switch (*sig++) {
case 'd':
lua_pushnumber(L, va_arg(vl, double));
break;
case 'i':
lua_pushinteger(L, va_arg(vl, int));
break;
case 's':
lua_pushstring(L, va_arg(vl, char *));
break;
case '>':
goto endargs;
default:
error(L, “invalid option (%c)", *(sig-1));
}
}
}
endargs:
nres = -nres;
while (*sig) {
switch(*sig++) {
case 'd': {
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 isnum;
int n = lua_tointeger(L, nres, &isnum);
if (!isnum)
error(L, "wrong result type");
*va_arg(vl, int *) = n;
break;
}
case 's': {
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++;
}