C API-table操作

获取table字段值

想要获取table字段的值,首先需要确定table在栈中的位置,知道了table的索引之后,在通过lua提供的函数来获取字段值

   int lua_getfield (lua_State *L, int idx, const char *k)

示例:
test_table.lua

    background = {r=0.30, g=0.10,b=0}

main.cc

#include 
#include 
#include 

#ifdef __cplusplus
extern "C" {
#include "lua.h"
#include "lauxlib.h"
}

#endif // __cplusplus
#define MAX_COLOR 255
void error(lua_State *L, const char* fmt, ...) {
    va_list argp;
    va_start(argp, fmt);
    vfprintf(stderr, fmt, argp);
    va_end(argp);
    lua_close(L);
    exit(EXIT_FAILURE);
}


int getfield(lua_State* L, int index, const char* key) {
    int result;
    lua_getfield(L, index, key);//table 中的key会入栈 table 索引此时会变成 -2
    if (!lua_isnumber(L, -1)) {
        error(L, "invalid bakcground color");
    }

    result = (int)(lua_tonumber(L, -1) * MAX_COLOR);
    lua_pop(L, 1); //从栈弹出一个元素,即刚刚放入的 table的key对应的值
    return result;
}

void load(lua_State* L, const char* fname) {
    if (luaL_loadfile(L, fname) || lua_pcall(L, 0, 0, 0)) {
        //luaL_loadfile\lua_pcall 发生错误,两个函数都会把错误消息压入栈,并返回一个非零的错误代码,可以通过lua_tostring获得错误信息
        error(L, "error cannot run config  file:%s\n", lua_tostring(L, -1));
    }

    lua_getglobal(L, "background"); //将lua脚本中的全局变量 background 入栈
    
    int red = getfield(L, -1, "r");
    int green = getfield(L,-1, "g");
    int blue = getfield(L,-1, "b");

    printf("red =%d , green=%d, blue=%d\n", red, green, blue);
}

int main() {
    lua_State* L = luaL_newstate();
    int weight = 0;
    int height = 0;
    load(L, "./load_table.lua");
    lua_close(L);
    system("pause");
}

设置table的key的值

设置table的key的值需要用到lua_setfield函数, 同样的使用这个函数时,也需要知道 table 的索引

LUA_API void lua_setfield (lua_State *L, int idx, const char *k);

但是这里用到了另外两个函数

 void lua_newtable(lua_State *L); //实际上是个宏, 创建一个新的table, 并将其压入栈
 void lua_setglobal (lua_State *L, const char *name) //给栈顶变量设置名字,并把栈顶元素弹出

示例代码:
main.cc

#include 
#include 
#include 

#ifdef __cplusplus
extern "C" {
#include "lua.h"
#include "lauxlib.h"
}

#endif // __cplusplus
#define MAX_COLOR 255

static void stack_dump(lua_State *L) {
    int i;
    int top = lua_gettop(L);//
    printf("stack len:%d  ", top);
    for (i = 1; i <= top; i++) {
        int t = lua_type(L, i);
        switch (t) {
        case LUA_TSTRING: {
            printf("'%s'", lua_tostring(L, i));
            break;
        }
        case LUA_TBOOLEAN: {
            printf(lua_toboolean(L, i) ? "true" : "false");
            break;
        }
        case LUA_TNUMBER: {
            printf("%g", lua_tonumber(L, i));
            break;
        }
        default:
            printf("%s", lua_typename(L, t));
            break;
        }
        printf("  ");
    }
    printf("\n");
}

void error(lua_State *L, const char* fmt, ...) {
    va_list argp;
    va_start(argp, fmt);
    vfprintf(stderr, fmt, argp);
    va_end(argp);
    lua_close(L);
    exit(EXIT_FAILURE);
}

struct ColorTable {
    const char *name;
    unsigned char red, green, blue;
};

int getfield(lua_State* L, int index, const char* key) {
    int result;
    lua_getfield(L, index, key);//table 中的key会入栈 table 索引此时会变成 -2
    if (!lua_isnumber(L, -1)) {
        error(L, "invalid bakcground color");
    }

    result = (int)(lua_tonumber(L, -1) * MAX_COLOR);
    lua_pop(L, 1); //从栈弹出一个元素,即刚刚放入的 table的key对应的值
    return result;
}

void setfield(lua_State *L, const char *key, int value) {
    lua_pushnumber(L, (double)value / MAX_COLOR);
    lua_setfield(L, -2, key);
}

void setcolor(lua_State* L, struct ColorTable* ct) {
    lua_newtable(L); //创建一个新的table, 并将其压入栈
    stack_dump(L);
    setfield(L, "r", ct->red);
    setfield(L, "g", ct->green);
    setfield(L, "b", ct->blue);

    int red = getfield(L, -1, "r");
    int green = getfield(L, -1, "g");
    int blue = getfield(L, -1, "b");

    printf("red =%d , green=%d, blue=%d\n", red, green, blue);

    lua_setglobal(L, ct->name); //给栈顶变量设置名字,并把栈顶元素弹出
    stack_dump(L);
}

int main() {
    lua_State* L = luaL_newstate();
    ColorTable colortable[] = {
        {"WHITE", MAX_COLOR, MAX_COLOR, MAX_COLOR},
        {"RED", MAX_COLOR, 0, 0},
        {"GREEN", 0, MAX_COLOR, 0},
    };
    
    for (int i = 0; i < 3; i++) {
        setcolor(L, &colortable[i]);
    }

    lua_close(L);
    system("pause");
}

你可能感兴趣的:(C API-table操作)