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 <stdio.h>
#include <string.h>
#include <stdlib.h>

#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 <stdio.h>
#include <string.h>
#include <stdlib.h>

#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");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章