2012-12-20 3 views
2

Мой вопрос правда похож на это: How to create nested Lua tables using the C APIВозвращение многомерного массива из C в Lua

Я думал, что я понял, что ответ, но я по-прежнему есть проблемы.

У меня есть массив объектов, которые я пытаюсь вернуть.

 const char * pushlist[] = { 
       "status", "cmdsequence", "timestamp", "gain", 
     }; 
     int nItems = sizeof(pushlist)/sizeof(char *); 
     int iDepth = -(1 + nItems); 

     // // 
     // What we want to do is essentially push an array of tables. 
     // The tables have keys (see pushlist above) and values. 
     // The array is indexed by integers from 1 through N. 
     // 
     lua_newtable(L); 
     for(Json::Value::UInt i = 0; i != totFrames; i++) 
     { 
      lua_pushnumber(L, i + 1); // push the array index 
      lua_newtable(L); 

      Json::Value frame = params["frameinfo"][i]; 

      // now push the table which will be at array index (i + 1) 
      for(int n = 0; n < nItems; n++) 
      { 
       lua_pushstring(L, pushlist[n]);     // push key 
       lua_pushnumber(L, frame[pushlist[n]].asUInt()); // push value 
      } 
      lua_settable(L, iDepth); 
      lua_settable(L, -3); // (note 1) error here 
     } 
     lua_settable(L, iDepth); // (note 2) not clear on the need for this 
     lua_settable(L, -3); 
     lua_setglobal(L, "framedata"); 

Так в Lua я хочу видеть:
[0] = {[ "Статус"] = 1, [ "cmdsequence"] = 2, [ "метка"] = 3, [ "усиление" ] = 4}
...
[totFrames-1] = {["status"] = 5, ["cmdsequence"] = 6, ["timestamp"] = 7, ["gain"] = 8}

Я не понимаю, что такое 2 lua_settable для примечания 2, но ответ, который я связал выше, указывает, что они нужны.

Ошибка lua_settable (L, -3) (примечание 1). Я делаю это на C++, и поэтому у меня этот код заключен в скобки в try/catch. Когда он попадает в эту настройку, первый раз сворачивает и переходит к моему улову. Я думаю, что я как-то повредил стек, но я этого не вижу.


Спасибо @Omri Barel за отличный ответ. Я все еще не понимаю, что делать после внутреннего цикла for.

теперь у меня есть это: константный символ * pushlist [] = { "статус", "cmdsequence", "метка", "усиление", }; int nItems = sizeof (pushlist)/sizeof (char *);

 // // 
     // What we want to do is essentially push an array of tables. 
     // The tables have keys (see pushlist above) and values. 
     // The array is indexed by integers from 1 through N. 
     // 
     lua_newtable(L); 
     for(Json::Value::UInt i = 0; i != totFrames; i++) 
     { 
      lua_pushnumber(L, i + 1); // push the array index 
      lua_newtable(L); 

      Json::Value frame = params["frameinfo"][i]; 

      // now push the table which will be at array index (i + 1) 
      for(int n = 0; n < nItems; n++) 
      { 
       lua_pushnumber(L, frame[pushlist[n]].asDouble()); // push value 
       lua_setfield(L, -2, pushlist[n]); 
      } 
      lua_settable(L, -3); // (note 1) error here 
     } 
     //lua_settable(L, -3);  <<-- not certain that this is required 
     lua_setglobal(L, "framedata"); 

Я больше не взорваюсь, но мой Lua терпит неудачу (сообщение об ошибке отсутствует, оно просто выходит). Я подозреваю, что я не повредил стек, но почему-то я не закончил эту таблицу правильно, и поэтому мое возвращение сбито с толку.

Я вставляю несколько других возвращаемых значений в стек Lua перед этим массивом, а затем еще один после него.

Мой Lua вызов выглядит так:

 param1,param2,framedata,Err = CCall.ReadFromC(arg, arg); 

Я, наконец, эту работу. Он нуждается в дальнейшем тестировании, но пока кажется правильным. Еще раз спасибо @Omri Barel. Вот фрагмент кода, с которым я столкнулся.

 const char * pushlist[] = { 
       "status", "cmdsequence", "timestamp", "gain", 
     }; 
     int nItems = sizeof(pushlist)/sizeof(char *); 

     // // 
     // What we want to do is essentially push an array of tables. 
     // The tables have keys (see pushlist above) and values. 
     // The array is indexed by integers from 1 through N. 
     // 
     lua_newtable(L); 
     for(Json::Value::UInt i = 0; i != totFrames; i++) 
     { 
      Json::Value frame = params["frameinfo"][i]; 

      // now push the table which will be at array index (i + 1) 
      lua_newtable(L); 
      for(int n = 0; n < nItems; n++) 
      { 
       const char * itemName = pushlist[n]; 
       if(frame[itemName].isNull()) continue; 
       lua_pushnumber(L, frame[pushlist[n]].asDouble()); // push value 
       lua_setfield(L, -2, pushlist[n]); 
      } 
      lua_rawseti(L, -2, i + 1); 
     } 
+1

При установке 'х [я] = y' с' i' быть номером, я предлагаю вам использовать 'lua_rawseti' вместо' lua_pushnumber' последовал по 'lua_settable'. –

ответ

6

Проблема в том, что вы нажимаете слишком много пар ключ/значение, прежде чем добавлять их в таблицу. Вы должны добавить одну пару за раз.

Когда вы отлаживаете Lua, самое лучшее, что вы можете сделать, это очень часто выгружать содержимое стека, чтобы проверить, что происходит. В «Programming In Lua» есть код «сбрасывания стека» (для этого достаточно первого издания).

Давайте посмотрим на ваш код (внутри цикла кадров).

  1. Вы создаете стол.Стек:

    ... [таблица]

  2. Нажимаешь пар ключ/значение:

    ... [таблица] [ключ] [значение] [ключ] [значение] [ ключ] [значение] [клавиша] [значение]

  3. Вы вызываете устанавливаемый с iDepth, что не выглядит правильным для меня. В этом случае iDepth = -(1+nItems) = -5. Но вы нажимаете пары, так что это должно быть вдвое больше. Но даже если iDepth были правы, вы все равно вызываете его один раз, поэтому он удаляет только одну пару из стека:

    ... [table] [key] [value] [key] [value] [ ключ] [значение]

  4. Вы вызываете устанавливаемый с -3, но -3 является [значением], чтобы вы получили сообщение об ошибке.

Вы должны вызывать устанавливаемое (с -3) после каждой пары ключ/значение.

И я также предложил бы использовать setfield, который немного яснее. Вместо того, чтобы:

lua_pushstring(L, key); 
lua_pushnumber(L, value); 
lua_settable(L, -3); 

Вы можете использовать:

lua_pushnumber(L, value); 
lua_setfield(L, -2, "key"); 
+0

Еще раз спасибо @Omri Barel. Я сейчас работаю и не мог бы сделать это без тебя. Я выложу свой последний код выше. – halm

+0

@halm Рад, что я мог бы помочь ;-) –

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