Lua 学习 chapter28
目录
- 基础知识
- 操作表
- 一些简便方法
- 调用lua函数
回顾复习加巩固,自己应该认真地学习复习和巩固,并不是只有学习新知识是自己最重要的,而是复习和巩固才是自己最重要的,所以自己每天必须抽出一定的时间对自己的学习进行复习和巩固。
基础知识
lua可以作为配置文件来供c语言使用,例如我们来定义一个窗口的大小。
1
2
width = 200
height = 300
然后我们使用LuaAPI来指挥lua语言解析该文件,并获取width和height的值。
- luaL_loadfile(lua_State *L, fname):加载文件并且编译,返回一个执行这个文件的函数,放到栈顶
- lua_pcall(L,0,0,0):调用栈中的函数,第二个参数为函数参数的个数,第三个参数为返回值的个数,第四个参数为错误处理函数。在压入结果之前,pcall函数会将参数和函数出栈,将返回值从第一个按照顺序压入栈中。至于最后一个参数为零,则lua会把错误信息作为string压倒栈中,如果是函数,第四个参数为它在栈中的索引,一般这个错误处理函数应该在被压入栈且位于待调用函数之下。
- lua_getglobal(lua_State *L, const char *key):根据key值获取全局变量,并放到栈顶。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include<stdio.h>
#include<string.h>
#include<stdarg.h>
#include<stdlib.h>
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
int getglobint(lua_State L, const char var);
void load(lua_State L, const char fname, int w, int h);
void error(lua_State L, const char fmt, …);
int main(void)
{
lua_State* L = luaL_newstate();//打开lua
luaL_openlibs(L);//打开标准库
<span class="kt">int</span> <span class="n">width</span><span class="p">,</span> <span class="n">height</span><span class="p">;</span>
<span class="n">load</span><span class="p">(</span><span class="n">L</span><span class="p">,</span> <span class="s">"config"</span><span class="p">,</span> <span class="o">&</span><span class="n">width</span><span class="p">,</span> <span class="o">&</span><span class="n">height</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"%d %d"</span><span class="p">,</span> <span class="n">width</span><span class="p">,</span> <span class="n">height</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
}
int getglobint(lua_State L, const char var)
{
int isnum, result;
lua_getglobal(L, var);//将相应的全局变量的值压入到栈中。
result = (int)lua_tointegerx(L, -1, &isnum);
if (!isnum)
{
error(L, "'%s' should be a number n", var);
}
lua_pop(L, 1);
return result;
}
void load(lua_State L, const char fname, int w, int h)
{
if (luaL_loadfile(L,fname) || lua_pcall(L,0,0,0))//loadfile加载代码,pcall运行编译后的代码段
{
error(L, "cannot run config. file %s", lua_tostring(L,-1));
}
w = getglobint(L, "width");
h = getglobint(L, "height");
}
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);
}
}
操作表
现在我们要为每个窗口配置一种背景色,假设最终的颜色格式是由三个数字分量组成的RGB颜色。
1
2
3
4
width = 200
height = 300
BLUE = {red = 0,green = 0,blue = 1.0}
background = BLUE
我们可以对表进行操作,具体用到的函数:
- lua_pushstring(L,key)
- lua_gettable(L,-2) //-2是表的索引,它会pop出key,然后根据key取值,并把值放到栈中
- lua_getfield(L,-1,key)//相当于上面的两步,这个函数会返回结果的类型
- lua_pushnumber(L,val)
- lua_pushstring(L,key)
- lua_settable(L,-3)// -3是表的索引,它会pop出val,key,然后给表设置值。
- lua_setfield(L,-2,key)// 相当于上面的两步,它会pop出val然后根据key设置值。
- lua_createtable(L,int narr,int nrec):narr,表示连续的值个数,nrec表示hash的值个数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include<stdio.h>
#include<string.h>
#include<stdarg.h>
#include<stdlib.h>
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
const int MAX_COLOR = 255;
struct ColorTable
{
const char* name;
unsigned char red, green, blue;
}colortable[] = {
{"WHITE", MAX_COLOR, MAX_COLOR, MAX_COLOR},
{"RED", MAX_COLOR, 0, 0},
{"GREEN", 0, MAX_COLOR, 0},
{"BLUE", 0, 0, MAX_COLOR},
{NULL, 0, 0, 0}
};
int getglobint(lua_State L, const char var);
void load(lua_State L, const char fname, int w, int h);
void error(lua_State L, const char fmt, …);
void getColor(lua_State L, const char what, int r, int g, int b);
int getcolorfield(lua_State L, const char key);
void setcolor(lua_State L,struct ColorTable ct);
void setcolorfield(lua_State L, const char* index, int value);
int main(void)
{
lua_State* L = luaL_newstate();//打开lua
luaL_openlibs(L);//打开标准库
<span class="kt">int</span> <span class="n">width</span><span class="p">,</span> <span class="n">height</span><span class="p">,</span> <span class="n">red</span><span class="p">,</span> <span class="n">green</span><span class="p">,</span> <span class="n">blue</span><span class="p">;</span>
<span class="n">load</span><span class="p">(</span><span class="n">L</span><span class="p">,</span> <span class="s">"config"</span><span class="p">,</span> <span class="o">&</span><span class="n">width</span><span class="p">,</span> <span class="o">&</span><span class="n">height</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"%d %d </span><span class="se">n</span><span class="s">"</span><span class="p">,</span> <span class="n">width</span><span class="p">,</span> <span class="n">height</span><span class="p">);</span>
<span class="n">getColor</span><span class="p">(</span><span class="n">L</span><span class="p">,</span> <span class="s">"background"</span><span class="p">,</span> <span class="o">&</span><span class="n">red</span><span class="p">,</span> <span class="o">&</span><span class="n">green</span><span class="p">,</span> <span class="o">&</span><span class="n">blue</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">"%d</span><span class="se">t</span><span class="s">%d</span><span class="se">t</span><span class="s">%d</span><span class="se">n</span><span class="s">"</span><span class="p">,</span> <span class="n">red</span><span class="p">,</span> <span class="n">green</span><span class="p">,</span> <span class="n">blue</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="n">colortable</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">name</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">setcolor</span><span class="p">(</span><span class="n">L</span><span class="p">,</span> <span class="o">&</span><span class="n">colortable</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
}
int getglobint(lua_State L, const char var)
{
int isnum, result;
lua_getglobal(L, var);
result = (int)lua_tointegerx(L, -1, &isnum);
if (!isnum)
{
error(L, "'%s' should be a number n", var);
}
lua_pop(L, 1);
return result;
}
void load(lua_State L, const char fname, int w, int h)
{
if (luaL_loadfile(L,fname) || lua_pcall(L,0,0,0))
{
error(L, "cannot run config. file %s", lua_tostring(L,-1));
}
w = getglobint(L, "width");
h = getglobint(L, "height");
}
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);
}
void getColor(lua_State L, const char what, int r, int g, int* b)
{
lua_getglobal(L, what);
if (!lua_istable(L,-1))
{
error(L, "'%s' is not a table", what);
}
<span class="o">*</span><span class="n">r</span> <span class="o">=</span> <span class="n">getcolorfield</span><span class="p">(</span><span class="n">L</span><span class="p">,</span> <span class="s">"red"</span><span class="p">);</span>
<span class="o">*</span><span class="n">g</span> <span class="o">=</span> <span class="n">getcolorfield</span><span class="p">(</span><span class="n">L</span><span class="p">,</span> <span class="s">"green"</span><span class="p">);</span>
<span class="o">*</span><span class="n">b</span> <span class="o">=</span> <span class="n">getcolorfield</span><span class="p">(</span><span class="n">L</span><span class="p">,</span> <span class="s">"blue"</span><span class="p">);</span>
}
int getcolorfield(lua_State L, const char key)
{
int result, isnum;
lua_getfield(L, -1, key);
result = (int)(lua_tonumberx(L, -1, &isnum) * MAX_COLOR);
if (!isnum)
{
error(L, "invalid component '%s' in color", key);
}
lua_pop(L, 1);
return result;
}
void setcolor(lua_State L, ColorTable ct)
{
lua_newtable(L);
setcolorfield(L, "red", ct->red);
setcolorfield(L, "green", ct->green);
setcolorfield(L, "blue", ct->blue);
lua_setglobal(L, ct->name);
}
void setcolorfield(lua_State L, const char index, int value)
{
lua_pushstring(L, index);
lua_pushnumber(L, double(value) / MAX_COLOR);
lua_settable(L, -3);
//lua_setfield(L, -2, index); lua_setfield是将pushstring和settable结合起来的
}
调用lua函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
//一个通用的调用函数
//这里vl其实就是一个指针,指向了参数的地址。
//
//va_start()所做的就是让vl指向函数的最后一个确定的参数(声明程序中是sig)的下一个参数的地址。
//
//va_arg()所做的就是根据vl指向的地址,和第二个参数所确定的类型,将这个参数的中的数据提取出来,作为返回值,同时让ap指向下一个参数。
//
//va_end()所做的就是让vl这个指针指向0。
void call_va(lua_State* L, const char* func, const char* sig, ...) {
va_list vl;
int narg, nres; //参数和结果的个数
<span class="n">va_start</span><span class="p">(</span><span class="n">vl</span><span c