lua c读取嵌套表

时间:2014-11-20 10:56:30

标签: c linux lua lua-table lua-api

下面是我需要从C中读取的lua表:

listen = {
    { port = 1234, address = "192.168.1.1", userdata = "liunx" },
    { port = 1235, address = "192.168.1.2", userdata = "liunx1" },
    { port = 1236, address = "192.168.1.3", userdata = "liunx2" }
}

下面是c代码:

#include <lua.h>                                /* Always include this when calling Lua */
#include <lauxlib.h>                            /* Always include this when calling Lua */
#include <lualib.h>                             /* Prototype for luaL_openlibs(), */
/*   always include this when calling Lua */

#include <stdlib.h>                             /* For function exit() */
#include <stdio.h>                              /* For input/output */

void bail(lua_State *L, char *msg){
    fprintf(stderr, "\nFATAL ERROR:\n  %s: %s\n\n",
            msg, lua_tostring(L, -1));
    exit(1);
}

int main(void)
{
    lua_State *L;
    L = luaL_newstate();                        /* Create Lua state variable */
    luaL_openlibs(L);                           /* Load Lua libraries */
    if (luaL_loadfile(L, "cfg.lua")) 
        bail(L, "luaL_loadfile() failed");
    if (lua_pcall(L, 0, 0, 0))           
        bail(L, "lua_pcall() failed");
    // how to read???
    lua_getglobal(L, "listen");
    lua_close(L);
    return 0;
}

我想旅行这个表格,其中可能包含while循环中的一些数据,但实际上不知道该怎么做,所以任何提示?

非常感谢您的提示!以下是工作代码:

#include <lua.h>                                /* Always include this when calling Lua */
#include <lauxlib.h>                            /* Always include this when calling Lua */
#include <lualib.h>                             /* Prototype for luaL_openlibs(), */
/*   always include this when calling Lua */

#include <stdlib.h>                             /* For function exit() */
#include <stdio.h>                              /* For input/output */

void bail(lua_State *L, char *msg)
{
    fprintf(stderr, "\nFATAL ERROR:\n  %s: %s\n\n",
            msg, lua_tostring(L, -1));
    exit(1);
}

int main(void)
{
    lua_State *L;

    static struct {
        const char * name;
        int type;
    } fields[] = {
        {"port", LUA_TNUMBER},
        {"address", LUA_TSTRING},
        {"userdata", LUA_TSTRING},
        {NULL, 0}
    };

    L = luaL_newstate();                        /* Create Lua state variable */
    luaL_openlibs(L);                           /* Load Lua libraries */

    if (luaL_loadfile(L, "cfg.lua")) 
        bail(L, "luaL_loadfile() failed");

    if (lua_pcall(L, 0, 0, 0))           
        bail(L, "lua_pcall() failed");

    lua_getglobal(L, "listen");
    luaL_checktype(L, -1, LUA_TTABLE);

    int i;
    for (i = 1; ; i++) {
        lua_rawgeti(L, -1, i);
        if (lua_isnil(L, -1)) {
            lua_pop(L, 1);
            break;
        }
        // an element of the 'listen' table should now be at the top of the stack
        luaL_checktype(L, -1, LUA_TTABLE);
        // read the content of that element
        int field_index;
        for (field_index = 0; (fields[field_index].name != NULL 
                    && fields[field_index].name != NULL); field_index++) {

            lua_getfield(L, -1, fields[field_index].name);
            luaL_checktype(L, -1, fields[field_index].type);
            // you should probably use a function pointer in the fields table.
            // I am using a simple switch/case here
            switch(field_index) {
                case 0:
                    printf("port: %d\n", (int)lua_tonumber(L, -1));
                    // do what you want with port
                    break;
                case 1:
                    printf("address: %s\n", lua_tostring(L, -1));
                    break;
                case 2:
                    // handle userdata
                    printf("userdata: %s\n", lua_tostring(L, -1));
                    break;
            }
            // remove the field value from the top of the stack
            lua_pop(L, 1); 
        }
        // remove the element of the 'listen' table from the top of the stack.
        lua_pop(L, 1);
    }

    lua_close(L);

    return 0;
}

1 个答案:

答案 0 :(得分:7)

你不是太远了。这里的关键是要了解Lua API如何将堆栈用于所有内容。

这是一个未经测试的代码示例,可以帮助您:

// this will be used to validate our table
static struct {
    const char * name;
    int type;
} fields[] = {
    {"port", LUA_TNUMBER},
    {"address", LUA_TSTRING},
    {"userdata", LUA_TSTRING},
    NULL
};

lua_getglobal(L, "listen");

// the 'listen' table should be at the top of the stack
luaL_checktype(L, -1, LUA_TTABLE);

// iterate the listen table
int i;
for (i = 1; ; i++) {
    lua_rawgeti(L, -1, i);
    // when you get nil, you're done
    if (lua_isnil(L, -1)) {
        lua_pop(L,1);
        break;
    }
    // an element of the 'listen' table should now be at the top of the stack
    luaL_checktype(L, -1, LUA_TTABLE);
    // read the content of that element
    int field_index;
    for (field_index = 0; fields[field_index] != NULL; field_index++) {
        lua_getfield(L, -1, fields[field_index].name);
        luaL_checktype(L, -1, fields[field_index].type);
        // you should probably use a function pointer in the fields table.
        // I am using a simple switch/case here
        switch(field_index) {
        case 0:
            port = lua_tonumber(L, -1);
            // do what you want with port
            break;
        case 1:
            address = lua_tostring(L, -1);
            break;
        case 2:
            // handle userdata
            break;
        }
        // remove the field value from the top of the stack
        lua_pop(L, 1); 
    }
    // remove the element of the 'listen' table from the top of the stack.
    lua_pop(L, 1);
}

我建议您使用这些文档:Lua API table Lua API ref