Lua 学习 chapter28

13k 词

目录

  1. 基础知识
  2. 操作表
  3. 一些简便方法
  4. 调用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">&#34;config&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">width</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">height</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">&#34;%d %d&#34;</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">&#34;config&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">width</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">height</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">&#34;%d %d </span><span class="se">n</span><span class="s">&#34;</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">&#34;background&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">red</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">green</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">blue</span><span class="p">);</span>
<span class="n">printf</span><span class="p">(</span><span class="s">&#34;%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">&#34;</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">&amp;</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">&#34;red&#34;</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">&#34;green&#34;</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">&#34;blue&#34;</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