简体   繁体   中英

How to make a structure in C language with lua c api

How to create the following C language structure using Lua c api?

typedef struct _c{
    int d;
} obj_c;
typedef struct _b{
    obj_c c[4];
}obj_b;
typedef struct _a{
    obj_b b;
}obj_a;
obj_a a[4];

The above structure in lua a[1].bc[1].d = 1; I try to use it together, but it doesn't work. Error Message: PANIC: unprotected error in call to Lua API (attempt to index a number value)

in lua a[1].bc = 1; To use like this, I wrote the following code. This code works normally.

lua_createtable(L, 2, 0); // stack: {} : -1
{
    lua_pushnumber(L, 1); // stack: {}, 1 : -2
    {
        lua_newtable(L); // stack: {}, 1, {} : -3

        lua_createtable(L, 0, 1); // stack: {}, 1, {}, {} : -4
        lua_pushnumber(L, 49);
        lua_setfield(L, -2, "c");

        lua_setfield(L, -2, "b");
        lua_settable(L, -3);
    }
    lua_pushnumber(L, 2); // stack: {}, 2 : -2
    {
        lua_newtable(L); // stack: {}, 2, {} : -3

        lua_createtable(L, 0, 1); // stack: {}, 2, {}, {} : -4
        lua_pushstring(L, 50);
        lua_setfield(L, -2, "c");

        lua_setfield(L, -2, "b");
        lua_settable(L, -3);
    }
}
lua_pop(L, -2);
lua_setglobal(L, "a");

What do I do a[1].bc[1].d = 1; Can it be made in the same form?

At first you use lua_pop not correctly, the main usage is to remove number of top elements from stack. In lua.h #define lua_pop(n) lua_settop(L, -(n)-1) , in your case it will be the same as lua_settop(L, 1) in your case it may be OK, but if there is something in stack (like arguments) it may lead to failure. In your code lua_pop is not needed at all as your stack on this line already filled table, so it must be:

lua_createtable(L, 2, 0); // stack: {}
{
    lua_pushnumber(L, 1); // stack: {}, 1
    {
        lua_newtable(L); // stack: {}, 1, {}

        lua_createtable(L, 0, 1); // stack: {}, 1, {}, {}
        lua_pushnumber(L, 49);
        lua_setfield(L, -2, "c"); // stack: {}, 1, {}, {c=49}

        lua_setfield(L, -2, "b"); // stack: {}, 1, {b={c=49}}
        lua_settable(L, -3); // stack: {1 = {b={c=49}}}
    }
    lua_pushnumber(L, 2); // stack: {1 = {b={c=49}}}, 2
    {
        lua_newtable(L); // stack: {1 = {b={c=49}}}, 2, {}

        lua_createtable(L, 0, 1); // stack: {1={b={c=49}}}, 2, {}, {}
        lua_pushstring(L, 50);
        lua_setfield(L, -2, "c"); // stack: {1={b={c=49}}}, 2, {}, {c=50}

        lua_setfield(L, -2, "b"); // stack: {1={b={c=49}}}, 2, {b={c=50}}
        lua_settable(L, -3); // stack: {1={b={c=49}}, 2={b={c=50}}}
    }
}
lua_setglobal(L, "a"); // stack is empty, _G.a={ {b={c=49}}, {b={c=50}}}

If you want to make field c as array of tables, instead of lua_pushunmber(L, 49) and lua_pushnumber(L, 50) , replace with following code:

lua_newtable(L);          // stack:...,{}
lua_pushnumber(L, 1);     // stack:...,{},1
lua_newtable(L);          // stack:...,{},1,{}
lua_pushnumber(L, 1);     // stack:...,{},1,{},1
lua_setfield(L, -2, "d"); // stack:...,{},1,{d=1}
lua_settable(L, -3);      //stack:...,{1={d=1}}

So in your stack instead of number will be filled table.

To create empty structure like in C:

/*typedef struct _c{
    int d;
} obj_c;
typedef struct _b{
    obj_c c[4];
}obj_b;
typedef struct _a{
    obj_b b;
}obj_a;
obj_a a[4];*/

int i,j;
lua_createtable(L, 4, 0); //obj_a[4]
for (i = 1; i <= 4; i++) { // adding 4 tables obj_a
  lua_createtable(L, 0, 1); //obj_a
  lua_createtable(L, 4, 0); //obj_c[4]
  for (j = 1; j <= 4; j++) { // adding 4 tables obj_c
    lua_createtable(L, 0, 1); //obj_c
    lua_pushinteger(L, 0); //default d value
    lua_setfield(L, -2, "d"); //{d=0}
    lua_seti(L, -2, j); //add table obj_c to array
  }
  lua_setfield(L, -2, "b"); // {b=obj_c[4]}
  lua_seti(L, -2, i); //add table obj_a to array
}
lua_setglobal(L, "a");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM