2017-08-15 137 views
1

我悲慘地無法將嵌套的Lua錶轉換爲C json對象。我正在使用LuaTableToJson(請參閱此處的代碼),其中「index」是要檢索的參數索引,並且PopOneArg該例程根據其類型處理值。從Lua到Lua的Lua嵌套表

當有一個嵌套表我想要遞歸調用LuaTableToJson,但與索引= -1它不起作用。

問:可以在工作的樣本中檢索作爲參數傳遞從Lua爲C.嵌套表從Lua通過嵌套表C.

時,或者可能有人解釋堆棧結構請人點謝謝

注意:對於C-> Lua我有一個解決方案。

STATIC json_object *LuaTableToJson (lua_State* luaState, int index) { 
    int idx; 

    json_object *tableJ= json_object_new_object(); 
    const char *key; 
    char number[3]; 
    lua_pushnil(luaState); // 1st key 
    for (idx=1; lua_next(luaState, index) != 0; idx++) { 

     // uses 'key' (at index -2) and 'value' (at index -1) 
     if (lua_type(luaState,-2) == LUA_TSTRING) key= lua_tostring(luaState, -2); 
     else { 
      snprintf(number, sizeof(number),"%d", idx); 
      key=number; 
     } 
     json_object *argJ= PopOneArg(luaState, -1); 
     json_object_object_add(tableJ, key, argJ); 
     lua_pop(luaState, 1); // removes 'value'; keeps 'key' for next iteration 
    } 

    // Query is empty free empty json object 
    if (idx == 1) { 
     json_object_put(tableJ); 
     return NULL; 
    } 
    return tableJ; 
} 

STATIC json_object *PopOneArg (lua_State* luaState, int idx) { 
    json_object *value=NULL; 

    int luaType = lua_type(luaState, idx); 
    switch(luaType) { 
     case LUA_TNUMBER: { 
      lua_Number number= lua_tonumber(luaState, idx);; 
      int nombre = (int)number; // evil trick to determine wether n fits in an integer. (stolen from ltcl.c) 
      if (number == nombre) { 
       value= json_object_new_int((int)number); 
      } else { 
       value= json_object_new_double(number); 
      } 
      break; 
     } 
     case LUA_TBOOLEAN: 
      value= json_object_new_boolean(lua_toboolean(luaState, idx)); 
      break; 
     case LUA_TSTRING: 
      value= json_object_new_string(lua_tostring(luaState, idx)); 
      break; 
     case LUA_TTABLE: { 
      if (idx > 0) { 
       value= LuaTableToJson(luaState, idx); 
      } else { 
       value= json_object_new_string("UNSUPPORTED_Lua_Nested_Table"); 
      } 
      break;     
     }  
     case LUA_TNIL: 
      value=json_object_new_string("nil") ; 
      break; 

     default: 
      AFB_NOTICE ("PopOneArg: script returned Unknown/Unsupported idx=%d type:%d/%s", idx, luaType, lua_typename(luaState, luaType)); 
      value=NULL; 
    } 

    return value;  
} 

static json_object *LuaPopArgs (lua_State* luaState, int start) {  
    json_object *responseJ; 

    int stop = lua_gettop(luaState); 
    if(stop-start <0) return NULL; 

    // start at 2 because we are using a function array lib 
    if (start == stop) { 
     responseJ=PopOneArg (luaState, start); 
    } else { 
     // loop on remaining return arguments 
     responseJ= json_object_new_array(); 
     for (int idx=start; idx <= stop; idx++) { 
      json_object *argJ=PopOneArg (luaState, idx); 
      if (!argJ) goto OnErrorExit; 
      json_object_array_add(responseJ, argJ);  
     } 
    } 

    return responseJ; 

    OnErrorExit: 
    return NULL; 
} 
+1

'lua_next',整數密鑰,和'lua_tostring'不拌勻,檢查[手冊](http://www.lua.org/manual/5.2/manual.html#lua_tolstring)和此[SO問題](https://stackoverflow.com/questions/29287988/iterating-over-table-of-tables-with-the-lua-c-api/29288604#29288604) – Adam

+0

'編號'會超過'99'長度?如果是這樣,創建一個更大的數組。 – ryyker

+0

我不瞭解你的評論。 lua_string工作的很好,當妥善處理。對於99,甚至不理解與問題的關係。與導入嵌套表的關係是什麼? – Fulup

回答

1

對於一個打包的解決方案,檢查我的代碼here

本質,解析嵌套表時,你應該在負指數解析。在這種情況下,lua_next會將堆棧與您正在跟蹤的索引相混淆,因此您需要將其減少。

您可以嘗試

if (index < 0) index--; // change to -- as in your code 

當分析表。它應該與你的代碼一起工作,但我不能保證沒有我錯過的另一個問題。

我的代碼肯定適用於任何級別的嵌套,因此我建議您將其作爲示例並在發佈後將其作爲答案發布。

+0

事實上,檢查你的代碼是if(index <0)index--;這是需要的。非常感謝你沒有你的幫助。沒有你的提議,我永遠不會找到這個訣竅。我的代碼是從github.com/iotbzh/audio-bindings/blob/master/Controller-afb/...訪問。從代碼我先前交,唯一的變化是比lua_next(luaState,索引)在循環之前我需要添加如果(指數<0)index--; - 昨天Fulup – Fulup