How to read the amount of entries the lua in C code - c

How can I do a count of the amount of settings that exist in my file lua
My file is as follows:
name =
{
Activename = true; // setting 1
}
name1 =
{
Activename1 = true; // setting 2
}
name2 =
{
Activename2 = true; // setting 3
}
My lua code that I am trying to read the amount is below:
lua_getglobal(L, "name");
lua_getfield(L, -1, "Activename");
varenable = lua_toboolean(L, -1);
lua_getglobal(L, "name1");
lua_getfield(L, -1, "Activename1");
varenable = lua_toboolean(L, -1);
lua_getglobal(L, "name2");
lua_getfield(L, -1, "Activename2");
varenable = lua_toboolean(L, -1);
I want to create a message like this:
printf ("There are 3 settings in Userconf.lua file"/n);
Now that comes the question how do I make it to the lua, because I need a variable that the value of the amount of settings, e.g.:
printf("there are %d settings in Userconf.lua file\n", Amount_to_settings);

Related

Error occurs attempt to index field in lua_getfield

I have a lua code where it is showing index error the error occurs when reading result
I'm using lua_gettop(L) for the index
My table is:
Avatar =
{
one = {
vals = 51,
result = 300,
}
}
My code is:
void read_test(void) {
lua_State *L;
L = luaL_newstate();
luaL_openlibs(L);
if (luaL_loadfile(L, "test.lua") || lua_pcall(L, 0, 0, 0))
{
printf("Error 'test.lua'\n");
return;
}
lua_getglobal(L, "Avatar");
lua_getfield(L, lua_gettop(L), "one");
lua_getfield(L, lua_gettop(L), "vals");
lua_getfield(L, lua_gettop(L), "result");
lua_close(L);
printf("Read complete.\n");
}
When reading the table, an error occurs
lua_getfield(L, lua_gettop(L), "result");
attempt to index field
What is the correct way for me to work this?
lua_getglobal(L, "Avatar");
lua_getfield(L, lua_gettop(L), "one");
lua_getfield(L, lua_gettop(L), "vals");
lua_getfield(L, lua_gettop(L), "result");
Each of these lua_getfield calls pushes a new item onto the stack. First you push Avatar, then you index into that the one field, then the vals field, but the last line is effectively trying to read Avatar.one.vals.result, which does not exist.
You probably need to call lua_remove(L, -1) to pop the top of the stack (vals) before your last line that attempts to index result

How to add a message of amount of settings

well I have a question, I was wondering if it is possible to count the settings that exist within a function lua_getglobal.
I have a file called define.lua he is as follows:
tbl {
macro_enable = true;
macro_value = 100;
time_expire = 60;
enable_mac = true;
};
What I'm trying to insert a message in my code to count the amount of existetes settings
code:
lua_getglobal(L, "tbl");
lua_getfield(L, -1, "macro_enable");
p->macro_enable = lua_toboolean(L, -1);
lua_getfield(L, -1, "macro_value");
p->macro_value = lua_tointeger(L, -1);
lua_getfield(L, -1, "time_expire");
p->time_expire = lua_tointeger(L, -1);
lua_getfield(L, -1, "enable_mac");
p->enable_mac = lua_toboolean(L, -1);
Want to add a message.
printf ("% d configurations have been read");
I tried to do a loop more without success
If you can't use a loop then start with
Int count=0;
And on each line you read a config field:
Count+=1;
Your printf statement should say:
printf ("% d configurations have been read",count);

luaL_setmetatable() overrides metatables from other values

I have different metatables in my project. But if I create a value A and assign the metatable "X" and creates a second value B and attach metatable "Y", A gets the Y metatable, too! Here is a simplified C function for demonstration:
#include <errno.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
// shoudl create t["obj"] = <userdata> with metatable = "Obj" but gets "OtherType"
int create_table_with_object(lua_State *L)
{
lua_newtable(L);
lua_pushlightuserdata(L, (void*)0x1234);
luaL_setmetatable(L, "Obj"); // This Type is already registered with lua_newmetatable()
lua_setfield(L, -2, "obj");
luaL_newmetatable(L, "OtherType");
lua_pushinteger(L, 70);
lua_setfield(L, -2, "ICameFromOtherType");
lua_pop(L, 1); // just a dummy table
// If we create another userdata object, the first one
// gets the same type as this one!
// Obj -> changes to "OtherType"
// ### CRITICAL SECTION STRT ###
lua_pushlightuserdata(L, (void*)0x5555);
luaL_setmetatable(L, "OtherType");
lua_setglobal(L, "JustADummyObj"); // this removes the value from the stack!
// ### CRITICAL SECTION END ###
return 1;
}
int main(void)
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
luaL_loadfile(L, "bug.lua");
lua_pushcfunction(L, create_table_with_object);
lua_setglobal(L, "create_table_with_object");
luaL_newmetatable(L, "Obj");
lua_pop(L, 1);
int error;
if(error = lua_pcall(L, 0, 0, 0))
{
fprintf(stderr, "Fatal error: \n");
fprintf(stderr, "%s\n", lua_tostring(L, -1));
return 1;
}
lua_close(L);
return 0;
}
Lua Code:
local a = create_table_with_object()
print(getmetatable(a.obj).__name)
The output is "OtherType" but it should be "Obj". It seems that the second call to lua_setmetatable() overrides the table from other values?!
Ok, solved!
lightuserdata in Lua shares one metatable (instead of one metatable per value). So changing the table for a lightuserdata value changes all other lightuserdata values!

lua c read nested tables

below is the lua table i need 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 travel this table which may contain a few number of data in while loop, but really do not know how to do it, so any tips?
Thanks very much for your tips!Below are the worked 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;
}
You are not too far. The key here is to understand how the Lua API use the stack for everything.
Here is an untested code sample which should get you going:
// 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 those documentations: Lua API table Lua API ref

Iterate through a table in Lua, in a function called from C

I'm trying to call a Lua function from C. The Lua function creates a table and then iterates through it. It works as expected when called from Lua, but not when I call it from a C program. Is there any reason why I can't do what I'm trying here?
test.lua:
function f()
t = {["a"] = "aaa", ["b"] = "bbb", ["c"] = "ccc"}
for z, v in t do
print(t .. " " .. v)
end
end
test.c:
#include <string.h>
#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
int main(void)
{
char read_buffer[1024];
lua_State *L = lua_open();
luaL_openlibs(L);
if (luaL_loadfile(L, "test.lua") || lua_pcall(L, 0, 0, 0))
fprintf(stderr, "Error loading test.lua");
lua_getglobal(L, "f");
if(lua_pcall(L, 0, 0, 0) != 0)
fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
strncpy(read_buffer, lua_tostring(L, -1), sizeof(read_buffer));
lua_pop(L, 1);
printf("got from lua: %s\n", read_buffer);
lua_close(L);
return 0;
}
Thanks!
I'm noticing a couple of issues above that's causing problems.
Over here:
function f()
t = {["a"] = "aaa", ["b"] = "bbb", ["c"] = "ccc"}
for z, v in t do
print(t .. " " .. v)
end
end
You can't use a lua table in the for in loop like that unless you make t callable in someway (eg. using __call for instance). More likely you're probably just trying to iterate through it, in which case you would use pairs:
for z, v in pairs(t) do
-- etc.
The other error is that you're trying to concat strings onto the table. Not sure what you were intending here. Perhaps you wanted to print the table address? You can use tostring for that.
The second issue I notice is in your C code:
if(lua_pcall(L, 0, 0, 0) != 0)
So you're not expecting f to return anything unless there's an error. But right after that you try to convert the top item into a string:
strncpy(read_buffer, lua_tostring(L, -1), sizeof(read_buffer));
lua_pop(L, 1);
printf("got from lua: %s\n", read_buffer);
which doesn't make a whole lot of sense -- there may not be anything on the stack at this point. This is clearly a logic error in your code. If this is suppose to be a part of the error handling you should enclose it in braces so it's properly scoped:
if(lua_pcall(L, 0, 0, 0) != 0)
{
fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
strncpy(read_buffer, lua_tostring(L, -1), sizeof(read_buffer));
lua_pop(L, 1);
printf("got from lua: %s\n", read_buffer);
}

Resources