【问题标题】:How to get the complicated arguments of a Lua function in C language?如何在 C 语言中获取 Lua 函数的复杂参数?
【发布时间】:2015-02-19 03:27:36
【问题描述】:

我的 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);

    ......
}

【问题讨论】:

  • 您应该在您的注释行的堆栈顶部有一个 3 元素数组。您可以像以前一样使用lua_rawgeti 来获取值,然后使用lua_tointeger 来获取值。 (此外,像 #FFFFFF 这样的颜色文字在 vanilla Lua 中不存在)
  • 你是如何从 lua 中表示颜色的?例如,对于{#EEEEEE,30.0,30.0}#EEEEEE 是什么?是字符串还是代表rgb的整数?
  • 此时您应该查看用户数据。你给它提供了很好的 Lua 元方法,并使它成为一个真正的 C 结构,你会得到一个漂亮干净的界面。
  • @greatwolf,#EEEEEE应该是一个整数,我只是用#EEEEEE来代表一种颜色。
  • @dualed,对不起,你的意思和greatwolf 一样吗?

标签: c lua lua-table lua-api


【解决方案1】:

我要做的是将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

【讨论】:

  • 非常感谢@greatwolf,您向我展示了我需要的所有代码,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-04
  • 1970-01-01
  • 1970-01-01
  • 2021-04-19
  • 1970-01-01
相关资源
最近更新 更多