参考《Programming in Lua》第25章的内容,主要是call_va通用调用函数,整理了如下的例子:
/*
* gcc -o c_lua c_lua.c liblua.a -lm -ldl
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
void handle_error(lua_State *L, const char *fmt, ...) {
va_list argp;
va_start(argp, fmt);
vfprintf(stderr, fmt, argp);
va_end(argp);
fprintf(stderr, "%s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
//e.g.: call_va("f", "dd>d", x, y, &z);
int 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:
handle_error(L, "invalid option (%c)", *(sig - 1));
return -1;
}
}
endargs:
nres = strlen(sig); /* number of expected results */
/* do the call */
if (lua_pcall(L, narg, nres, 0) != 0) {/* do the call */
handle_error(L, "error calling '%s': ", func);
return -1;
}
nres = -nres; /* stack index of first result */
while (*sig) { /* repeat for each result */
switch (*sig++) {
case 'd': /* double result */
if (!lua_isnumber(L, nres)) {
handle_error(L, "wrong result type");
return -1;
}
*va_arg(vl, double *) = lua_tonumber(L, nres);
break;
case 'i': /* int result */
if (!lua_isnumber(L, nres)) {
handle_error(L, "wrong result type");
return -1;
}
*va_arg(vl, int *) = lua_tointeger(L, nres);
break;
case 's': /* string result */
if (!lua_isstring(L, nres)) {
handle_error(L, "wrong result type");
return -1;
}
*va_arg(vl, const char **) = lua_tostring(L, nres);
break;
default:
handle_error(L, "invalid option (%c)", *(sig - 1));
return -1;
}
nres++;
}
va_end(vl);
return 0;
}
int main(void)
{
char buff[256];
int error;
lua_State *L = luaL_newstate();
luaL_openlibs(L);
sprintf(buff, "function transform(x)\n"
" return x/100\n"
"end\n");
printf("%s\n", buff);
error = luaL_loadbuffer(L, buff, strlen(buff), "transform") || lua_pcall(L, 0, 0, 0);
if (error) {
fprintf(stderr, "%s", lua_tostring(L, -1));
lua_pop(L, 1);
} else {
int x = 3;
double r;
/*lua_getglobal(L, "transform");
lua_pushnumber(L, x);
if (lua_pcall(L, 1, 1, 0) == 0) {
r = lua_tonumber(L, -1);
lua_pop(L, 1);
printf("r %f\n", r);
}*/
if (call_va(L, "transform", "i>d", x, &r) == 0) {
printf("Result: transform(%d) = %f\n", x, r);
}
}
lua_close(L);
return 0;
}