2014-12-20 2 views
2

Мои функции Lua вызовут функции C, один из которых очень сложный, как показано ниже, как я могу получить все аргументы в C? Аргумент colors представляет собой массив элементов типа структуры {color, x, y} и имеет неопределенный номер. Аргумент region является структурным типом {x, y, width, height}.Как получить сложные аргументы функции Lua на языке C?

/* 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); 

    ...... 
} 
+0

У вас должен быть 3-элементный массив в верхней части стека в вашей прокомментированной строке. Вы можете использовать 'lua_rawgeti', как вы должны были получить значение, а затем' lua_tointeger', чтобы получить значение. (Кроме того, цветные литералы, такие как '# FFFFFF', не существуют в ваниле Lua) –

+0

Как вы представляете цвет от lua? Например, с '{# EEEEEE, 30.0,30.0}', что такое '# EEEEEE'? Это строка или это целое число, представляющее rgb? – greatwolf

+0

На этом этапе вы должны заглянуть в userdata. Вы даете ему хорошие метаметоды для Lua и превращаете их в настоящую структуру на C, и вы получаете хороший чистый интерфейс. – dualed

ответ

2

Что бы я сделал это прекращаться логику обработки для pixel_t из Lua таблицы в отдельную функцию. Это сделает код более приемлемым и легче рассуждать. Что-то вроде lua_topixel_t следующий C API подписи конвенции Lua в:

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, измените, по мере необходимости, lua_topixel_t.

+0

Большое спасибо @greatwolf, вы показываете мне все коды, которые мне нужны, спасибо! – Suge

Смежные вопросы