将多维数组从C返回到Lua

hal*_*alm 2 c++ lua

我的问题与此类似: 如何使用C API创建嵌套的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" );
Run Code Online (Sandbox Code Playgroud)

所以在Lua中我想看到:
[0] = {["status"] = 1,["cmdsequence"] = 2,["timestamp"] = 3,["gain"] = 4}
...
[totFrames -1] = {["status"] = 5,["cmdsequence"] = 6,["timestamp"] = 7,["gain"] = 8}

我不清楚注2中2 lua_settable的用途,但我上面提到的答案表明它们是必需的.

lua_settable(L,-3)(注1)错误输出.我在C++中这样做,所以我把这个代码放在try/catch中.当它第一次出现并击中我的捕获时它击中了那个可设置的.我想我已经以某种方式破坏了堆栈,但我没有看到它.


感谢@Omri Barel的出色答案.在内部'for'循环之后,我仍然不清楚要做什么.

我现在有这个: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++ )
        {
            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" );
Run Code Online (Sandbox Code Playgroud)

我不再爆炸,但我的Lua失败了(没有错误消息,它只是退出).我怀疑我没有损坏堆栈,但不知怎的,我没有正确完成这个表,所以我的回报很困惑.

我将几个其他返回值推送到此数组之前的Lua堆栈中,然后再推送一个.

我的Lua电话是这样的:

       param1,param2,framedata,Err = CCall.ReadFromC( arg, arg );
Run Code Online (Sandbox Code Playgroud)

我终于有了这个工作.它需要进一步测试,但到目前为止似乎是正确的.再次感谢@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);
        }
Run Code Online (Sandbox Code Playgroud)

Omr*_*rel 6

问题是在将它们添加到表之前,您正在推送太多的键/值对.您应该一次添加一对.

在调试Lua时,您可以做的最好的事情是经常转储堆栈的内容,以检查发生了什么.在" Programming In Lua "中有一些"堆栈转储"代码(第一版对此非常好).

我们来看看你的代码(在frame循环中).

  1. 你创建一个表.堆栈是:

    ...... [表]

  2. 你推了一对键/值:

    ... [table] [key] [value] [key] [value] [key] [value] [key] [value]

  3. 你打电话给settable iDepth,这对我来说不合适.在这种情况下iDepth = -(1+nItems) = -5.但是你正在推动对,所以它应该是双倍的.但即使iDepth是正确的,你仍然只调用一次,所以它只从栈中删除一对:

    ... [table] [key] [value] [key] [value] [key] [value]

  4. 你用-3调用settable,但-3是[value],所以你得到一个错误.

你应该在每个键/值对之后调用settable(带-3).

而且我也建议使用setfield哪个更清楚一些.代替:

lua_pushstring(L, key);
lua_pushnumber(L, value);
lua_settable(L, -3);
Run Code Online (Sandbox Code Playgroud)

您可以使用:

lua_pushnumber(L, value);
lua_setfield(L, -2, "key");
Run Code Online (Sandbox Code Playgroud)