声明:lua是一个跨平台的脚本语言,在linux下也可以使用,但是我目前只使用过windows,这篇文章也是在windows下的编程。
1.lua的简介
百度百科的简介:
Lua 是一个小巧的脚本语言。是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组,由Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo所组成并于1993年开发。 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译,运行。Lua并没有提供强大的库,这是由它的定位决定的。所以Lua不适合作为开发独立应用程序的语言。Lua 有一个同时进行的JIT项目,提供在特定平台上的即时编译功能。
2.下载lua
lua官网的下载页面:http://www.lua.org/download.html
3.lua包含的文件
下载后的lua是一个压缩包,解压后可以获得doc和src文件夹,还有makefile和readme文件。
doc文件夹下主要有lua的api文档
src文件夹包含lua的源码
(lua压缩包并不包含lib文件,lib文件直接通过vs去编译lua源代码就可以生成lib了,方法见第四步)
4.生成lua lib文件。
使用visual studio添加静态库项目(静态库项目的生成方法见此链接)
5.使用lua
lauxlib.h,lua.h,luaconf.h,lualib.h这几个头文件。
关于lua的使用,我直接用代码说明吧。
以下代码演示了lua的栈操作 ,执行内存脚本,加载脚本中定义的变量,执行脚本中定义的无参函数,执行脚本中定义的有参函数,脚本中调用C++函数等操作。
1. // lua_test.cpp : 定义控制台应用程序的入口点。
2. //
3.
4. #include "stdafx.h"
5.
6. #include <iostream>
7. #include <string>
8.
9. extern "C"
10. {
11. #include "lua.h"
12. #include "lualib.h"
13. #include "lauxlib.h"
14. }
15.
16. using namespace std;
17.
18.
19. int fcAdd(lua_State *lu)
20. {
21. int a = lua_tointeger(lu, 1);
22. int b = lua_tointeger(lu, 2);
23. //结果压栈
24. return 1; //返回1个结果
25. }
26.
27.
28. int _tmain(int argc, _TCHAR* argv[])
29. {
30.
31. int nret = 0;
32.
33. /*创建Lua对象*/
34. lua_State* lu = luaL_newstate();
35. luaL_openlibs(lu);
36.
37.
38. /*栈操作 */
39. //压入一个int类型的数据,数值为1
40. lua_pushinteger(lu, 1);
41. //压入一个int类型的数据,数值为3
42. lua_pushinteger(lu, 3);
43. //获得栈中第一个元素(也就是刚刚放入的第一个元素“1”)
44. int n = lua_tointeger(lu, 1);
45. //获得栈中第二个元素
46. n = lua_tointeger(lu, 2);
47. //获得栈中的元素总数(如果总数为0,表示空。前面放入两个,这里的值为2)
48. int nStack = lua_gettop(lu);
49. //剔除栈中元素(剔除两个,栈空)
50. lua_pop(lu, 2);
51. //获得栈中元素总数
52. nStack = lua_gettop(lu);
53.
54. /*执行内存脚本*/
55.
56. //在lua脚本中,print函数是打印操作,print("Hello world")相当于打印一句Hello world。此时str相当于脚本中的打印操作
57. "print (\"Hello world!\")";
58. //把str加载到内存中,其中最后一个参数"name"是chunk名字,用于debug或者错误信息的标识
59. "line");
60. //调用函数。PS:lua_pcall的参数中n-nargs表示参数的个数,r-nresults表示...,errfunc表示
61. lua_pcall(lu, 0,0,0);
62.
63. /*加载脚本中定义的变量 */
64. "../../luaScripts/test.lua");
65. //压入aa名字(必须先压入需要取值的数据名,然后通过取值函数(例如tointeger) 从栈中取值)
66. "aa");
67. //压入bb名字
68. "bb");
69. //前面已经演示过传入正数索引调用tointeger,现在演示如果传入的参数为负数,则会从后开始取值
70. int bb = lua_tointeger(lu, -1);
71. int aa = lua_tointeger(lu, -2);
72.
73. /*执行脚本中定义的无参函数 */
74. //压入hello函数名字,其实无论函数还是变量,都是通过压入名字然后去调用的。
75. "hello");
76. //参数nargs为0,表示调用的是无参的函数
77. nret = lua_pcall(lu, 0,0,0);
78.
79. /*执行脚本中定义的有参函数 */
80. "fadd");
81. //压入即将作为参数的对象
82. lua_pushnumber(lu, aa);
83. lua_pushnumber(lu, bb);
84. //调用函数并获得返回结果(如果nret为0,表示调用成功,返回值会放入栈,通过取值即可获得。否则失败,失败时lua会产生失败信息放入栈,通过取值就可以获得错误信息)
85. nret = lua_pcall(lu, 2,1,0);
86.
87.
88. "1 元素总数:" << lua_gettop(lu) << endl;
89. if (nret != 0)
90. {
91. //打印错误信息
92. const char *pc = lua_tostring(lu, -1);
93. cout << pc;
94.
95. "2 元素总数:" << lua_gettop(lu) << endl;
96. }
97. else
98. {
99. //打印结果
100. nret = lua_tointeger(lu, -1);
101. "调用脚本函数:" << endl;
102. " + " << bb << " = " << nret << endl;
103.
104. "3 元素总数:" << lua_gettop(lu) << endl;
105. //?
106. lua_pop(lu, 1);
107. "4 元素总数:" << lua_gettop(lu) << endl;
108. }
109.
110. /*脚本中调用C++函数*/
111. //压入c++函数
112. lua_pushcfunction(lu, fcAdd);
113. //取出fcAdd函数使用
114. "fcAdd");
115. //压入脚本函数
116. "fc");
117. //压入参数
118. lua_pushnumber(lu, aa);
119. lua_pushnumber(lu, bb);
120. //调用函数
121. nret = lua_pcall(lu, 2,1,0);
122.
123. if (nret != 0)
124. {
125. const char *pc = lua_tostring(lu, -1);
126. cout << pc;
127. }
128. else
129. {
130. nret = lua_tointeger(lu, -1);
131. "调用C++函数:" << endl;
132. " + " << bb << " = " << nret << endl;
133. lua_pop(lu, 1);
134. }
135.
136. lua_close(lu);
137. "pause");
138. return 0;
139. }
6.lua脚本的创建
lua脚本其实就是个文本文件,之后后缀名改为lua了,例如第五步的test.lua脚本,这里列出test.lua脚本的源码
1. aa=2;
2. bb=3;
3. function hello(a,b)
4. "Hello in script!")
5. end
6. function fadd(a,b)
7. return a+b
8. end
9. function fc(a,b)
10. return fcAdd(a,b)
11. end