如何在C语言中获取Lua函数的复杂参数?

时间:2014-12-20 09:24:37

标签: c lua lua-table lua-api

我的Lua函数将调用C函数,其中一个函数非常复杂如下,如何获取C中的所有参数?参数colors{color, x, y}结构类型元素的数组,它具有不确定的数字计数。参数region{x, y, width, height}结构类型。

/* the function in Lua:
    findColors {
        colors={{#FFFFFF,0.0,0.0}, 
                {#EEEEEE,30.0,30.0}, 
                {#DDDDDD,20.0,40.0}},
        count=1, 
        region={10, 20, 100, 200}
     }
*/


typedef struct {
    int color;
    int x;
    int y;
} pixel_t;

static int findColorsProxy(lua_State *L)
{
    lua_settop(L, 1);
    luaL_checktype(L, 1, LUA_TTABLE);

    lua_getfield(L, 1, "colors");
    lua_getfield(L, 1, "count");
    lua_getfield(L, 1, "region");

    int colors_count = (int)lua_rawlen(L, -3);
    if (colors_count == 0) return 0;

    pixel_t *ps = NULL;
    for (int i = 0; i < colors_count; lua_pop(L, 1))
    {
        pixel_t *p_new = (pixel_t *)realloc(ret, sizeof(pixel_t));
        if (p_new == NULL) {
            if (ps != NULL) free(ps);
            return 0;
        }


        lua_rawgeti(L, 4, ++i);

        ... // I don't know what should I do next to get the pixels.
    }


    int count = (int)luaL_optinteger(L, -2, 0);

    int region_args_count  = (int)lua_rawlen(L, -1);
    if (region_args_count != 0 && region_args_count != 4) return 0;

    region_t rg;
    memset(&rg, 0, sizeof(region_t));
    for (int i = 0; i < region_args_count; lua_pop(L, 1))
    {
        lua_rawgeti(L, 4, ++i);
        int c = (int)luaL_checkinteger(L, -1);

        switch (i-1) {
            case 0:
                rg.x = c;
            case 1:
                rg.y = c;
            case 2:
                rg.width = c;
            case 3:
                rg.height = c;
        }
    }

    lua_pop(L, 3);

    ......
}

1 个答案:

答案 0 :(得分:2)

我要做的是将pixel_t的处理逻辑从lua表中断成一个单独的函数。这将使代码更容易理解和更容易推理。类似于lua_topixel_t之后的lua的C api签名约定:

bool lua_topixel_t(lua_State *L, int t, pixel *p)
{
  if (lua_type(L, t) != LUA_TTABLE) return false;
  if (!p) return false;

  int i = 0;
  lua_rawgeti(L, t, ++i);
  p->color = lua_tointeger(L, -1);
  lua_rawgeti(L, t, ++i);
  p->x = lua_tointeger(L, -1);
  lua_rawgeti(L, t, ++i);
  p->y = lua_tointeger(L, -1);

  lua_pop(L, i);
  return true;
}

现在只需在findColorsProxy

中使用它即可
pixel_t *ps = (pixel_t *) malloc(sizeof(pixel_t) * colors_count);
for (int i = 0; i < colors_count; lua_pop(L, 1))
{
  // ..., -3 = colors, count, region
  lua_rawgeti(L, -3, ++i);
  // ..., colors, count, region, -1 = color[i]
  if (!lua_topixel_t(L, -1, &ps[i - 1]))
  {
    free(ps); return 0;
  }
}
// ...

注意,我不确定你是如何从lua方面表示rgb颜色所以我只是假设它是一个整数。如果表示不同,例如lua字符串,请根据需要修改lua_topixel_t