Lua c read nested tables

below is the lua table I have to read from C:

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" } } 

below is the c code:

 #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; } 

I want to move this table, which may contain some data during the loop, but I really don't know how to do this, so any advice?

Thanks for the tips! Below is the code:

 #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; } 
+5
source share
1 answer

You are not too far. The key point here is understanding how the Lua API uses the stack for everything.

Here is an example of untested code that should catch you:

 // 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); } 

I suggest you use these documents: Lua API table Lua API ref

+7
source

Source: https://habr.com/ru/post/1207295/


All Articles