C语言调用Lua函数

参考《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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值