1lua是一个轻量级脚本语言,嵌入宿主语言程序中工作。用C写成的一个库,与C/C++交互性较好。
2保留关键字。大小写敏感。and, break, do, else, elseif, end, false, for, function, if, in, local, nil, not, or, while, then, repeat, return, true, nutil
3字符串。单引号或双引号定义,也可用方括号定义。用“,"号或".."号连接。
4注释。以两横"=="开始到行尾(类似C的//),或以--[ ]--之间(类似C的/* */)
5类型。lua是动态类型语言,无类型定义,值本身携带了自已的类型。
(1)nil:无意义值;
(2)Boolean:ture/false;
(3)number:双精度浮点数;
(4)string:字符串;
(5)userdata:一块原生的内存;
(6)thead:用于实现coroutine(与系统线程相似效果,但与系统线程无关);
(7)table:关联数组;
(8)function:函数。
6控制结构。
(1)while <exp> do <sentence> end
(2)repeat <sentence> until <exp>
(3)if <exp> then <sentence> {elseif <exp> then <sentence> } [else <sentence>] end
(4)for <name>=<first>,<last> do <sentence> end 或者是for <namelist> in <array> do <sentence> end
(5)条件表达式。只有false和nil是假,其它都是真(如0和空串也是真)
7语句组。chunk 可以是一个语句,也可以是一组语句的组合,还可以是一个函数。
语句块。brack 。do brock end
命令行使用
语法: lua [ -eil ] [script [arg ] ]
例:
$ lua -e "print(math.sin(2))" //直接执行chuck,
$ lua hello.lua //执行hello.lua文件的chunk。
$ lua -la -lb //先后执行a,b文件作为一个chunk。
$ lua -i //进入交互模式,以下命令都是在交互模式下进行。
>dofile("hello.lua") //加载hello.lua文件
>hello() //执行hello()函数,假设该函数已在刚加载的hello.lua文件中定义
>print(i) //打印变量i的值,假设i在hello.lua中定义或在先前定义
>n=math.sin(30) //把右表达式的值赋给变量n
>print(n) //
与宿主语言通信
(1)堆栈方式。入栈lua_push*,lua_getglobal()lua脚本文件中的变量或函数名入栈,取值lua_to*,查询lua_is*,lua_gettop(),出栈lua_pop(),lua_remove()。其它lua_settop(),lua_pushValue(),lua_insert(),lua_replace(),lua_type()。
(2)伪索引。用于访问不在栈上的lua值,如线程环境,函数环境,注册表,C函数的upvalue
(3)注册表。C保存的lua值,用伪索引LUA_REGSTRYINDEX
(4)错误处理。long jmp机制。
在C/C++中使用
(1)使用前先创建一个lua环境(一个表)。使用完成后关闭该环境。
(2)lua.h 定义了lua的基本API。以lua_开头的函数
luaxlib.h 一个辅助库,基本API的进一步封装,更实用的API。以luaL_开头的函数。
lualib.h 定义了打开指定包库的函数。
(3)lua环境创建时并没有加载预定义的函数库,需手动加载所需函数库包。
(4)luaL_loadfile() 加载lua脚本文件
lua_pcall() 运行(函数)。先函数名入栈,参数依次入栈,再调用lua_pcall(),最后依次从栈中取出结果。
lua_getglobal() lua脚本文件中的全局变量或函数名入栈,其它堆栈操作见上。
例:
--hello.lua
sname = "hello"
nage = 24
tblue = {r=0.2, g=0.3, b=0.4}
backgroud = tblue
function add(a, b)
c = a+b;
return a, b, c;
end
// main.cpp
#include "lua.hpp"
#include<iostream>
using namespace std;
int main()
{
lua_State *L = lua_open();/* opens Lua */
luaopen_base(L); /* opens the basic library */
luaopen_table(L); /* opens the table library */
//luaopen_io(L); /* opens the I/O library */
luaopen_string(L); /* opens the string lib. */
luaopen_math(L); /* opens the math lib. */
//加载并运行lua脚本文件
if (luaL_loadfile(L, "hello.lua") || lua_pcall(L, 0, 0, 0) )
luaL_error(L, "cannot run 'hello.lua' file : %s", lua_tostring(L, -1) );
//从lua脚本文件中取出全局变量
lua_getglobal(L, "sname");//把wight的值压入堆栈
if (!lua_isstring(L, -1) )
luaL_error(L, "sname should be a string!\n"); //»áÖ±½Ó½áÊø³ÌÐò
const char *name = lua_tostring(L, -1);//从堆栈中取出值并转换成字符串
cout<<"name="<<name<<endl;
lua_getglobal(L, "nage");
int nAge= lua_tonumber(L, -1);//数字
cout<<"age="<<nAge<<endl;
lua_getglobal(L, "backgroud");//把表backgroud压入到堆栈-1位置
if (!lua_istable(L, -1) )
luaL_error(L, "backgroud should be a table!\n");
lua_pushstring(L, "r");//把key压入-1位置,表backgroud退为-2位置
lua_gettable(L, -2);//取出backgroud[key]值并替换key压入堆栈-1位置,表backgroud仍为-2位置
double dRed= lua_tonumber(L, -1);
lua_pop(L, 1);//弹出-1位置的值,此时表backgroud进为-1位置
lua_pushstring(L, "g");
lua_gettable(L, -2);
double dgreen= lua_tonumber(L, -1);
lua_pop(L, 1);
lua_pushstring(L, "b");
lua_gettable(L, -2);
double dblue= lua_tonumber(L, -1);
cout<<"r="<<dRed<<", g="<<dgreen<<", b="<<dblue<<endl;
//操作lua脚本文件中的函数
lua_getglobal(L, "add");//函数名压栈-1位置
lua_pushnumber(L, 3);//参数a压栈-1位置,add退为-2位置
lua_pushnumber(L, 4);//参数b压栈
if(lua_pcall(L, 2, 3, 0) )//调用函数,指明有2个参数,3个输出结果,无出错处理函数
luaL_error(L, "running function 'add':%s", lua_tostring(L,-1));
int a = lua_tonumber(L, -3);//依次从栈中取出结果
int b = lua_tonumber(L, -2);
int c = lua_tonumber(L, -1);
cout<<a<<"+"<<b<<"="<<c<<endl;
lua_close(L);
}
//makefile
hello:main.cpp
g++ -o hello main.cpp -llua
clean:
rm hello $ make
$ ./hello
name=hello
age=24
r=0.2, g=0.3, b=0.4
3+4=7