lua要快点学
作者:Tsukasa
常用的Lua代码片段
表操作 :
a={}
新建空表。
a[1]
以数值索引表元素。
a={1,2}
指定元素初始化建立表,初始化元素从1开始索引,完成后a[1]元素值为1。
a.text
以键值索引表上某元素。
a[“text”]
与a.text等效。
a[text]
以text变量值为键值索引表上某元素,如text值为1,与a[1]等效。
a={x=1,y=2}
指定某键值初始化值建立表,完成后a.x元素值为1。
a={[“x”]=1,[“y”]=2}
与
a={x=1,y=2}等效。
a.func()
若a.func元素可调用,调用之。
a:func(b)
等效于
a.func(a,b)
字符串:
str=”abc”
创建字符串,以”abc”初始化。
str..”123”
连接字符串,结果为”abc123”。
#str
返回字符串长度。
逻辑操作:
true
逻辑真。
false
逻辑假,除逻辑表达式和两个逻辑值中的false外,只有nil值的逻辑值等于false,数值0和空字符串””都为true。
a==b
逻辑等于。
a~=b
逻辑不等于。
a and b
逻辑与。
a or b
逻辑或。
not a
逻辑非。
位操作:
lua本身没有提供位操作运算符或函数包,可以使用Bolt提供的lua函数BitAnd, BitOr;否则通过lua本身实现位操作相对麻烦。
结构化控制
if a then
func()
end
a的逻辑值为true时,调用func.
if a then
func1()
else
func2()
end
a的逻辑值为true时调用func1,否则调用func2.
for i=a,b,c do
func(i)
end
数值型for循环,循环变量i初始化为a,循环执行func(i) 和 i=i+c,当a与b相等时跳出循环.
for i=a,b do
func(i)
end
与
for i=a,b,1 do
func(i)
end
等效.
for k,v in pairs(t) do
func(k,v)
end
迭代型for循环,t为table类型变量,循环变量k,v每次循环时分别被赋值为t上一个元素的键和值,当表中所有元素被遍历之后跳出循环.如t={x=1,y=2},等效于依次执行func(“x”,1) func(“y”,2)
函数与闭包:
function func(a)
return a
end
定义定参函数func.
x = func (a)
调用函数func.
function add(a,b)
return c,d
end
在函数add中返回多个返回值。
x,y = add(a,b)
调用接收add的多个返回值,x被赋为c,y被赋为d.
x = add(a)
以缺省参数调用多参数函数,等效于add(a,nil);调用只接收部分返回值,x被赋为c.
function foo(a,b,…)
local arg={…}
end
定义变参函数,以…代表可变参数,以{…}建立可变参数表,arg[1]的值为第一个可变参数.
function fool(a,b)
return function(c)
c=a
return c
end
end
在函数fool的闭包中定义匿名函数并返回,在闭包中定义的函数可以直接使用闭包中的非局部变量a。要调用之,如
local f1 = fool(2,3)
local m = f1(4)
在闭包中定义函数,最直观的说明是,将一个函数定义写在另一个函数定义之内,那么这个位于内部的函数定义中便可以直接使用外部函数中的局部变量(称为非局部变量)。
在Bolt中,最经常使用闭包中定义函数技巧的场景是在定义事件回调中,因为回调函数的原型是被指定好的,要在回调函数中使用参数之外的额外信息,可以通过在闭包中定义回调函数并在其中访问非局部变量的方式来实现。
如Bolt中当在某对象上点击鼠标左键时,弹出一个显示变量a的值的对话框。事件回调函数的原型为void OnLButtonDown(UIObject, integer, integer) ,定义并设置回调的代码可以如下:(obj 为 UIObject对象)
local a = 5
obj:AttachListener(“OnLButtonDown”, true, function(pobj,x,y) XLMessageBox(tostring(a)) end)
调用
lua C
接口访问
lua
栈:
lua C接口索引lua栈上的元素,第一个压入战中的元素索引为1,第二个压入的元素索引为2,以此类推直到栈顶。还可以以栈顶为参考,使用负数索引来访问栈中的元素。此时,-1表示栈顶元素(最后压入的元素),-2表示栈顶开始第二个元素。
访问栈元素:
int lua_type(lua_State*L,int index)
返回栈上指定元素的类型。
int lua_is*(lua_State *L, int index)
判定栈上指定元素的类型是否可以转为指定类型。
*lua_to*(lua_State *L, int index)
将栈上指定元素转换为指定类型返回。
*luaL_check*(lua_State *L, int index)
检查栈上指定类型是否可转换为指定类型,如果不能,会在lua运行时中抛出脚本错误;否则转换为指定类型返回。
压入返回值
void lua_push*(lua_State*L, * value)
将C类型压入到lua 栈上。
如在C中定义原型为 integer func(string, integer, boolean)的lua函数,在C定义中如下:
static int func(lua_State* L)
{
const char * arg1 = lua_tostring(L,1);
int arg2 = lua_tointeger(L,2);
bool arg3 = lua_toboolean(L,3);
int result = 0;
//do something with args to get result
lua_pushinterger(L,result);
return 1;
}
操作
table
size_t lua_objlen (lua_State *L, int index);
获取栈上index索引指定的表的元素个数。
void lua_getfield (lua_State *L, int index, const char *k);
获取栈上index索引指定的表上键为k的元素,将之压到栈顶。
void lua_setfield (lua_State *L, int index, const char *k);
将栈上index索引指定的表上键为k的元素值置为栈顶元素值。
void lua_gettable (lua_State *L, int index);
获取栈上index索引指定的表上键为栈顶元素值的元素,将之压到栈顶。
void lua_settable (lua_State *L, int index);
将栈上index索引指定的表上键为栈顶开始第二个元素值的元素值置为栈顶元素值。
void lua_rawgeti (lua_State *L, int index, int n);
获取栈上index索引指定的表上下标为n的元素,将之压到栈顶。
如在lua中声明并以数值索引初始化一个table
local a = {1,2,3,4,5}
在C中遍历所有元素:(index变量为a元素在栈上的索引,L为所在lua_State指针)
size_t count = lua_objlen(L,index);
for(unsigned int ix = 1;ix <= count; ++ix)
{
lua_rawgeti(L, index, ix);
int value = lua_tointeger(L,-1);
do something with value
lua_pop(L,1);
}
若 如此初始化a
local a = {x=”x”,y=”y”}
在C中获取a.x 和 a.y的值:(index变量为a元素在栈上的索引,L为所在lua_State指针)
lua_getfield(L,index,”x”);
const char* x = lua_tostring(L,-1);
lua_pop(L,1);
lua_getfield(L,index,”y”);
const char*y = lua_tostring(L,-1);
lua_pop(L,1);
在
lua registry
上存取
:
lua registry是一个全局的table, 它只能被C代码访问,通常可以用它来保存需要在几个模块中共享的数据。lua registry总是位于一个伪索引值LUA_REGISTRYINDEX之上。
int ref = luaL_ref(L,LUA_REGISTRYINDEX);
将栈顶元素存入lua registry中, 返回在lua registry中的索引。
lua_rawgeti(L,LUA_REGISTRYINDEX, ref)
获取lua registry 上索引为ref的元素压入栈顶.
luaL_unref(L, LUA_REGISTYRINDEX,ref)
当不需要继续在lua registry中保留元素时,传入索引ref将之从lua registry上移出,以避免资源泄漏。
维护栈大小
int top = lua_gettop(L);
do something may change stack size
lua_settop(L, top);
lua stack上可以容纳的元素是有限的,而且会占用资源, 通常以成对的 lua_gettop 和 lua_settop调用来维护栈大小,保证其间的操作在栈上分配的局部对象不会在栈上保留,特别是在调用lua call执行了lua函数并有返回但忽略返回值时。
调用
lua
函数
XL_LRT_API long __stdcall XLLRT_LuaCall(lua_State* luaState,int args,int results,const wchar_t* contextInfo);
调用lua函数,args指定传入参数数量,栈顶为最后一个参数,向栈底方向栈上的元素顺次为倒数第二参数直到第一个参数,第一个参数之前为要调用的函数对象。调用完成之后,将函数对象极其之后的所有元素从栈上弹出,如果results指定为LUA_MULTRET将函数对象的所有返回值压入栈上,否则压入results个返回值;contextInfo字符串指定上下文信息,在调用的lua函数出现脚本错误时的回调中用做标识
。
在Bolt里用要求用XLLuaRuntime模块的XLLRT_LuaCall调用代替lua_*call类函数。
如lua 函数func,原型为
string,integer func(integer, string) , 在C中调用之:(index变量为func函数对象在栈上的索引,L为所在lua_State指针):
int top = lua_gettop(L);
lua_pushvalue(L,index);
lua_pushinteger(L,1);
lua_pushstring(L,”test”);
long result = XLLRT_LuaCall(L,2,2,L”for test”);
if(result == 0)
{
const char* ret1 = lua_tostring(L,-2);
int ret2 = lua_tointeger(L,-1);
do something for results/
}
lua_settop(L,top);
等效于在lua中调用func
ret1, ret2 = func(1,”test”)。
需要注意的是XLLRT_LuaCall的返回值,当为0时说明调用的lua函数被正确执行,否则说明lua函数执行中断,一般是出现了脚本错误,此时lua栈上是不会有func函数执行之后的返回值的,不能取返回值进行操作,或者继续执行依赖于func成功执行的任何操作。
原文地址:http://xldoc.xl7.xunlei.com/0000000018/00000000180001000031.html