lua学习笔记(4)——lua配置文件和table使用
来源:互联网 发布:java web静态资源分离 编辑:程序博客网 时间:2024/06/05 01:05
作为配置语言是lua的一个重要应用,lua文件在配置应用中非常灵活,可以直接读取文件中的全局量的值,也可以读取表以及嵌套表。
一、lua使用方式
个人理解,根据应用的场景和复杂程度,可以分为以下几种情况:
1、场景较简单,lua文件中使用全局量配置值
如:test.lua
-- configguration file for probram c
width = 200
height = 300
background_red = 0.30
background_green = 0.10
background_blue = 0
配置文件中都全局量,加载文件后,直接读取相应的值。
此种方式应用简单,但配置较多较复杂时,文件就会比较大,而且不方便分类。
2、场景较复杂,配置进行了分类,则lua文件中使用全局量+table(表)的方式进行配置
如:test.lua
-- configguration file for probram c
width = 200;
height = 300;
white =
{
r = 0;
g = 0;
b = 0;
}
blue =
{
r = 0;
g = 0;
b =
{
br =
{
brr = 110
};
bg = 11;
bb = 12;
}
}
black =
{
r = 1;
g = 1;
b = 10;
}
配置文件中有全局量,也有table(表),表之间还可以多重嵌套。简单的配置通过读取全局量获取,其他配置可以进行分类成表,再细分嵌套的表等。
3、场景复杂,针对不同版本不同客户进行分类,每一个版本下面的配置又要细分,则使用多个文件进行配置,公有的配置放在一个文件中,不同的配置放在不同的lua文件中,然后包含公有的lua文件(类似C中的include,但有差异)
如:global.lua
-- gllbal config
width = 200;
height = 300;
test.lua
dofile("../global.lua"); -- 把文件包含进来
white =
{
r = 0;
g = 0;
b = 0;
}
blue =
{
r = 0;
g = 0;
b =
{
br =
{
brr = 110
};
bg = 11;
bb = 12;
}
}
black =
{
r = 1;
g = 1;
b = 10;
}
此种方式可以灵活按照不通客户不通类型进行分类,配置使用灵活,可以满足绝大部分应用场景。
二、Lua配置文件使用
前面的学习中进行了基础的api操作,也熟悉了编写套路。
使用lua配置文件的基本步骤:
1、open lua环境 (lua_open)
2、加载标准库函数(luaL_openlibs)
3、加载lua文件并编译执行(luaL_loadfile、lua_pcall)
4、读取全局量和table
5、嵌套table的处理(类似C中的二维数组)
读取table有两种方法,后面会介绍。
示例代码:
int load(char *filename, int *width, int *height){ lua_State *L = lua_open(); luaL_openlibs(L); /* 打开lua包,加载标准库函数 */ /* 加载文件后,仅仅是将文件内容编译,在栈顶形成一个匿名函数, 调用lua_pcall调用该函数后,文件的内容才执行,之后才能访问全局量和函数等*/ if(luaL_loadfile(L, filename) || lua_pcall(L, 0, 0, 0)) { printf("cannot run configuration file :%s\n", lua_tostring(L, -1)); return 0; } /* 获取全局变量的值,每调用一次就把获取的值入栈 */ lua_getglobal(L, "width"); lua_getglobal(L, "height"); if(lua_isnumber(L, -2)) { *width = (int)lua_tonumber(L, -2); printf("width:%d\n", *width); } else { printf("width shoule be a number\n"); } if(lua_isnumber(L, -1)) { *height = (int)lua_tonumber(L, -1); printf("height:%d\n", *height); } else { printf("height shoule be a number\n"); } return 0;}int main(void){ int width = 0, height = 0; load("test.lua", &width, &height); return 0;}
三、读取table的方法
-- configuration file for program 'pp'width = 200; height = 300;white = {r = 0;g = 0;b = 0;}blue = {r = 0;g = 0;b = {br = {brr = 110};bg = 11;bb = 12;}}black = {r = 1;g = 1;b = 10;}
下面假设:t[K], t为table,k为表中我们要取值的标识,即key。
1、通过键值获取
lua_getglobal(L, t); /* 此处获取全局量,这里的全局量是一个table */
lua_pushstring(L, k); /* 将要取值的key入栈,这里类型对应,如lua_pushstring、lua_pushnumber等 */
lua_gettable(L, -2); /* 该函数取下表指定的table,然后将刚刚的key出栈并取得对应的值后,入栈,此时值在栈顶*/
lua_tostring(L, -1); /* 获得值 */
lua_pop(L, 1); /* 获得值后,将值出栈,还原原来的栈 */
嵌套的表也是类似的,每一次取值操作都会有入栈出栈操作,取值后会恢复原来的栈,所以不会破坏原来的栈。
看例子,跟踪栈的情况。
未嵌套:
C代码:
int load_table(char *filename, char *table){ lua_State *L = lua_open(); luaL_openlibs(L); /* 打开lua包,加载标准库函数 */ /* 加载文件后,仅仅是将文件内容编译,在栈顶形成一个匿名函数, 调用lua_pcall调用该函数后,文件的内容才执行,之后才能访问全局量和函数等*/ if(luaL_loadfile(L, filename) || lua_pcall(L, 0, 0, 0)) { printf("cannot run configuration file :%s\n", lua_tostring(L, -1)); return 0; } printf("stack 001:\n"); stackdump(L); /* 获取全局变量的值,每调用一次就把获取的值入栈 */ lua_getglobal(L, "width"); lua_getglobal(L, "height"); printf("stack 002:\n"); stackdump(L); lua_getglobal(L, table); printf("stack 003:\n"); stackdump(L); printf("//////////////\n"); lua_pushstring(L, "b"); printf("stack 003.1:\n"); stackdump(L); lua_gettable(L, -2); printf("stack 003.2:\n"); stackdump(L); lua_pushstring(L, "g"); printf("stack 003.3:\n"); stackdump(L); lua_gettable(L, -3); printf("stack 003.4:\n"); stackdump(L); lua_pop(L, 1); lua_pop(L, 1); printf("stack 003.5:\n"); stackdump(L); printf("/////////////////\n"); lua_close(L); return 0;}int main(void){ load_table("test.lua", "black"); return 0;}
运行结果:
$ ./lua_test
stack 001:
stack 002:
200 300
stack 003:
200 300 table
//////////////
stack 003.1:
200 300 table b
stack 003.2:
200 300 table 10
stack 003.3:
200 300 table 10 g
stack 003.4:
200 300 table 10 1
stack 003.5:
200 300 table
/////////////////
嵌套table:
C代码:
int load_table(char *filename, char *table){ lua_State *L = lua_open(); luaL_openlibs(L); /* 打开lua包,加载标准库函数 */ /* 加载文件后,仅仅是将文件内容编译,在栈顶形成一个匿名函数, 调用lua_pcall调用该函数后,文件的内容才执行,之后才能访问全局量和函数等*/ if(luaL_loadfile(L, filename) || lua_pcall(L, 0, 0, 0)) { printf("cannot run configuration file :%s\n", lua_tostring(L, -1)); return 0; } printf("stack 001:\n"); stackdump(L); /* 获取全局变量的值,每调用一次就把获取的值入栈 */ lua_getglobal(L, "width"); lua_getglobal(L, "height"); printf("stack 002:\n"); stackdump(L); lua_getglobal(L, table); printf("stack 003:\n"); stackdump(L); printf("//////////////\n"); lua_pushstring(L, "b"); printf("stack 003.1:\n"); stackdump(L); lua_gettable(L, -2); printf("stack 003.2:\n"); stackdump(L); lua_pushstring(L, "br"); printf("stack 003.2.1:\n"); stackdump(L); lua_gettable(L, -2); printf("stack 003.2.2:\n"); stackdump(L); lua_pushstring(L, "g"); printf("stack 003.3:\n"); stackdump(L); lua_gettable(L, -3); printf("stack 003.4:\n"); stackdump(L); lua_pop(L, 1); lua_pop(L, 1); lua_pop(L, 1); printf("stack 003.5:\n"); stackdump(L); printf("/////////////////\n"); lua_close(L); return 0;}int main(void){ load_table("test.lua", "blue"); return 0;}
运行结果:
$ ./lua_test
stack 001:
stack 002:
200 300
stack 003:
200 300 table
//////////////
stack 003.1:
200 300 table b
stack 003.2:
200 300 table table
stack 003.2.1:
200 300 table table br
stack 003.2.2:
200 300 table table table
stack 003.3:
200 300 table table table g
stack 003.4:
200 300 table table table nil
stack 003.5:
200 300 table
/////////////////
2、遍历table
lua_getglobal(L, t);
lua_pushnil(L);
while (lua_next(L, -2)) {
/* 此时栈上 -1 处为 value, -2处为 key */
lua_pop(L, 1); /* 取值后将值出栈,还原原来的栈 */
}
测试发现这种遍历方式是从后往前遍历的。
C代码:
int load_table(char *filename, char *table){ lua_State *L = lua_open(); luaL_openlibs(L); /* 打开lua包,加载标准库函数 */ /* 加载文件后,仅仅是将文件内容编译,在栈顶形成一个匿名函数, 调用lua_pcall调用该函数后,文件的内容才执行,之后才能访问全局量和函数等*/ if(luaL_loadfile(L, filename) || lua_pcall(L, 0, 0, 0)) { printf("cannot run configuration file :%s\n", lua_tostring(L, -1)); return 0; } printf("stack 001:\n"); stackdump(L); /* 获取全局变量的值,每调用一次就把获取的值入栈 */ lua_getglobal(L, "width"); lua_getglobal(L, "height"); printf("stack 002:\n"); stackdump(L); lua_getglobal(L, table); printf("stack 003:\n"); stackdump(L); lua_pushnil(L); while(lua_next(L, -2)) { printf("stack 004:\n"); stackdump(L); lua_pop(L, 1); printf("stack 004:\n"); stackdump(L); } lua_close(L); return 0;}int main(void){ load_table("test.lua", "black"); return 0;}
运行结果:
$ ./lua_test
stack 001:
stack 002:
200 300
stack 003:
200 300 table
stack 004:
200 300 table b table
stack 004:
200 300 table b
stack 004:
200 300 table g 0
stack 004:
200 300 table g
stack 004:
200 300 table r 0
stack 004:
200 300 table r
这里仅仅是给出了基本的操作方法,更复杂的 配置也是有这些基本的操作方法+字符串解析等实现。
到这里,lua作为配置用在C的基本操作和用法就学完了。
写这边文章参考了几篇大神的文章:
读取table:
http://www.jb51.net/article/58479.htm
https://www.cnblogs.com/billyrun/articles/5768627.html
C API函数介绍:
http://blog.csdn.net/yuliying/article/details/43412355
- lua学习笔记(4)——lua配置文件和table使用
- lua学习笔记—table
- Lua学习笔记--table
- lua学习笔记(2)——C语言调用lua的使用和测试
- lua学习笔记table表
- Lua学习笔记之table
- Lua笔记——2.表Table
- LUA学习笔记(一)——LUA的安装和配置。
- lua学习笔记(1)——lua简介和环境搭建
- lua学习03——table
- Lua 学习笔记(二) —— Scite 的配置文件讲解
- Lua 学习笔记(三) —— Scite 的配置文件修改
- 【Lua学习笔记】Lua中协程的使用
- lua学习:lua作配置文件
- lua学习:lua作配置文件
- Lua 学习笔记:C API 遍历 Table
- Lua 学习笔记:C API 遍历 Table
- lua学习笔记之table的遍历
- Fiori2.0学习笔记-modules
- Linux下同步时间及自动运行命令
- 单源最短路径之dijkstra算法
- 浅谈 PHP 与手机 APP 开发(API 接口开发)
- python 2 与 python 3 的pip 区分问题
- lua学习笔记(4)——lua配置文件和table使用
- 工作密钥、2磁道解密数据及密码计算
- 【1】 Kotlin学习之 BaseActivity.kt 文件
- XYNUOJ 1127: 分数加减法X
- IntelliJ Idea 常用快捷键列表
- python学习笔记(基础)
- zabbix编译安装
- Android 身份证号码的验证
- KEIL 编译器小知识