2013-06-07 3 views
1

Я создаю функцию C/C++, которая будет вызываться из Lua. Моя функция должна вызывать библиотечную функцию, подпись которой такова:Чтение Lua вложенных таблиц в C++

void libFunction(int val1, int val2, tSETTINGS * pSettings); 

Мне даны эти структуры C/C++.

typedef struct 
{ 
    int cmd; 
    int arg; 
} tCOMMAND; 
typedef struct 
{ 
    int numberCommands; 
    int id; 
    tCOMMAND commands[1]; 
} tSETTINGS; 

Может быть, мое мышление все неправильно на этом, но из Lua я звоню так:

id = 42 
val1 = 1 
val2 = 2 
cmd1 = { 3, 4 } 
cmd2 = { 5, 6 } 
commands = { cmd1, cmd2 } 
settings = { #commands, id, commands } 
mycfunction(val1, val2, settings) 

Я уверен, что я все еще не понимая Lua стека как указано в C++, поскольку то, что я пытаюсь, просто не работает. Мое решение может извлекать val1, val2, # команды и id, но когда я пытаюсь получить команды [0] и команды [1], я получаю {1, 2} и {2, 42} соответственно.

Мой C++ по существу такой (для этого образца я отбрасываю значения). Я уже получен val1 и val2:

int stkNdx = 1; 
lua_rawgeti(L, 3, stkNdx++); 
int numcmds = lua_tointeger(L, -1); // this successfully retrieves numberCommands 2 
lua_pop(L, 1); 
lua_rawgeti(L, 3, stkNdx++); 
int id = lua_tointeger(L, -1);  // this successfully retrieves id 42 
lua_pop(L, 1); 

lua_pushvalue(L, -1); 
lua_pushnil(L); 
int cmdNbr = 0; 
for(lua_next(L, -2); cmdNbr < numcmds; cmdNbr++) 
{ 
    lua_pushvalue(L, -2); 
    int cmd = lua_tointeger(L, -1); 
    int arg = lua_tointeger(L, -1); 
    lua_pop(L, 2); 
    lua_next(L, -2); 
} 
lua_pop(L, 1); 

Я пробовал различные перестановки lua_rawgeti() с последующим lua_tonumber() и lua_pop(), в основном с тем же результатом.

Это похоже на this question, и мое решение смоделировано после этого без успеха.

Экспериментирование больше я вставлен так:

lua_pushnil(L); 
while(lua_next(L, -2)) 
{ 
    if(! lua_istable(L, -1)) 
    { 
    int v = lua_tointeger(L, -1); 
    } 
    lua_pop(L, 1); 
} 

Этот цикл выполняется 4 раза. Первые 2 раза значения 2 и 42 присваиваются v. Следующие 2 итерации пропускают назначение (lua_istable возвращается true). Поэтому кажется, что, хотя я уже получил numcmds и id, они все еще там, в стеке. Я также явно не понимаю, как перебирать субтитры, когда они встречаются.

+0

I» Я попытался сделать это слишком некоторое время назад и закончил тем, что написал https://github.com/d-led/luastackcrawler. Как только вы сканируете стек, вы можете выйти из таблицы, также заботясь о круговых ссылках, но у меня пока нет достаточного теста, чтобы показать, что он работает. Вы можете внести свой вклад. Попробуйте это :). Место для запуска: [luavalue.h] (https://github.com/d-led/luastackcrawler/blob/master/luatablestack/luavalue.h) –

ответ

5

Показатели таблицы Lua варьируются от [1 .. N] вместо [0 .. N-1].

Ваш цикл должен быть:

int cmdNbr = 1; 
for(lua_next(L, -2); cmdNbr <= numcmds; cmdNbr++) 
{ 
    ... 
} 

или как я prever его:

lua_rawgeti(L, 3, 2); 
int id = lua_tointeger(L, -1);  // this successfully retrieves id 42 
lua_pop(L, 1); 

lua_rawgeti(L, 3, 3); 
{ 
    // commands table at stack top 
    size_t N = lua_objlen(L,-1); // size of the table 

    for (int i = 1; i <= N; ++i) 
    { 
     lua_rawgeti(L,-1, i); // cmd# at stack top 
     { 
      lua_rawgeti(L,-1,1); // first entry 
      int cmd = lua_tointeger(L,-1); 
      lua_pop(L,1); 

      lua_rawgeti(L,-1,2); // second entry 
      int arg = lua_tointeger(L,-1); 
      lua_pop(L,1); 
     } 
     lua_pop(L, 1); // pop cmd# 
    } 
} 
lua_pop(L, 1); // pop commands table 

отмечают, что, с функцией lua_objlen(L,idx), тем numcmds не нужно проходить

+0

, что означает, что cmd1 и cmd2 также должны варьироваться от [1 .. 2] – Enigma

+0

Большое спасибо. Я * думаю * Я понимаю ... попробует завтра, а потом, надеюсь, я * пойму. Еще раз спасибо. – halm

+0

Спасибо * Enigma * ..., который отлично сработал ... никаких изменений на то, что вы предложили. Еще лучше, я думаю, он это понимает. Благодарим за добавление комментариев к вашему предлагаемому коду. – halm

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