简单运行Lua代码
Lua是一个嵌入式的脚本语言,它不仅可以单独使用还能与其它语言混合调用。
GCC VC C++Builder extern "C" { ? 例一,简单运行Lua代码 #include <iostream> int main() ??? string s; ??? lua_close(L);//关闭 ??? 这已经是一个功能完备的交互方式Lua解释器了。 ??? 输入print "hello world" ??? 要调用Lua,首先要使用lua_open(对于5.0以后版本的Lua,建议使用luaL_newstate代替)产生一个lua_State,在使用完后调用lua_close关闭。
#include <iostream> ??? lua_State *L = luaL_newstate(); ??? //把一个数据送给Lua ??? //执行 ??? 这段代码把字符串中的key=value字符串全部转换成XML格式<key>value</key> void lua_pushnil (lua_State *L);??? lua_isnil (lua_State *L,int index); int??????????????? lua_toboolean (lua_State *L,int index); int? lua_gettop (lua_State *L); tb = {"abc",12,true,x=10,y=20,z=30} ??? 前三个数据可以用tb[1]~tb[3]取得 tb = {[1]="abc",[2]=12,[3] = true,["x"]=10,["y"]=20,["z"]=30} ??? 它的形式就是[key]=value,所谓的tb.x只是tb["x"]的语法糖而已,如果愿意,也可以用tb["x"]取得这个数据10。 ... ??? lua_State *L = luaL_newstate(); ??? //把一个tabele送给Lua ??? lua_pushstring(L,"Tag");// key ??? lua_pushstring(L,"Str");// key ??? lua_setglobal(L,"c"); //将栈顶元素(newtable)置为Lua中的全局变量c ??? //执行 ??????? //这个x应该是个table ??????? //弹出栈顶的x void lua_newtable (lua_State *L); 线程的环境(也就是放全局变量的地方)通常在伪索引 LUA_GLOBALSINDEX 处。 正在运行的 C 函数的环境则放在伪索引 LUA_ENVIRONINDEX 之处。 LUA_REGISTRYINDEX则存放着Lua注册表。 C函数UpValue的存放位置见上节。
{ ??? char *szLua_code = ??????? "a=10 " ??????? "b=/"hello/" " ??????? "c=true"; ? ??? lua_State *L = luaL_newstate(); ??? luaL_openlibs(L); ?? ??? //执行 ??? bool err = luaL_loadstring(L,0); ??? if(err) ??? { ??????? cerr << lua_tostring(L,-1); ??????? lua_pop(L,1); ??? } ??? else ??? { ??????? //遍历LUA_GLOBALSINDEX所在的table得到 ??????? lua_pushnil(L); ??????? while(0 != lua_next(L,LUA_GLOBALSINDEX)) ??????? { ??????????? // 'key' (在索引 -2 处) 和 'value' (在索引 -1 处) ??????????? /* ??????????? 在遍历一张表的时候,不要直接对 key 调用 lua_tolstring , ??????????? 除非你知道这个 key 一定是一个字符串。 ??????????? 调用 lua_tolstring 有可能改变给定索引位置的值; ??????????? 这会对下一次调用 lua_next 造成影响。 ??????????? 所以复制一个key到栈顶先 ??????????? */ ??????????? lua_pushvalue(L,-2); ??????????? printf("%s - %s ", ????????????????? lua_tostring(L,-1),??? //key,刚才复制的 ????????????????? lua_typename(L,lua_type(L,-2))); //value,现在排在-2的位置了 ??????????? // 移除 'value' 和复制的key;保留源 'key' 做下一次叠代 ??????????? lua_pop(L,2); ??????? } ??? } ??? lua_close(L); ??? return 0; } ? ??? LUA_REGISTRYINDEX伪索引处也存放着一个table,它就是Lua注册表(registry)。这个注册表可以用来保存任何C代码想保存 的Lua值。??? 加入到注册表里的数据相当于全局变量,不过只有C代码可以存取而Lua代码不能。因此用它来存储函数库(在下一节介绍)中的一些公共变量再好不过了。函数库??? 一个Lua库实际上是一个定义了一系列Lua函数的代码块,并将这些函数保存在适当的地方,通常作为table的域来保存。Lua的C库就是这样实现的。??? 作为一个完整的库,我们还需要写一个函数来负责把库中的所有公共函数放到table里,然后注册到Lua全局变量里,就像luaopen_*做的一样。 Lua为这种需求提供了辅助函数luaL_register,它接受一个C函数的列表和他们对应的函数名,并且作为一个库在一个table中注册所有这些 函数。下例中注册了一个名为Files的库,定义了三个库函数:FindFirst,FindNext,FindClose。extern "C" {#include "lua.h"#include "lualib.h"#include "lauxlib.h"} #include <iostream>#include <string>#include <windows.h>using namespace std; //函数库示例,Windows下查找文件功能//输入:string路径名//输出:userdata存放Handle(如果没找到,则是nil),string文件名int findfirst( lua_State *L ){??? WIN32_FIND_DATAA FindFileData;??? HANDLE hFind = ::FindFirstFileA(luaL_checkstring(L,1),&FindFileData);?????? if(INVALID_HANDLE_VALUE == hFind)??????? lua_pushnil(L);??? else??????? lua_pushlightuserdata(L,hFind);???? lua_pushstring(L,FindFileData.cFileName);?????? return 2;} //输入:userdata:findfirst返回的Handle//输出:string:文件名,如果没找到,则返回nilint findnext( lua_State *L ){??? WIN32_FIND_DATAA FindFileData;??? if(::FindNextFileA(lua_touserdata(L,&FindFileData))??????? lua_pushstring(L,FindFileData.cFileName);??? else??????? lua_pushnil(L);??? return 1;} //输入:userdata:findfirst返回的Handle//没有输出int findclose( lua_State *L ){??? ::FindClose(lua_touserdata(L,1));??? return 0;} //注册函数库static const struct luaL_reg lrFiles [] = {??? {"FindFirst",findfirst},??? {"FindNext",findnext},??? {"FindClose",findclose},??? {NULL,NULL}??? /* sentinel */};int luaopen_Files (lua_State *L) {??? luaL_register(L,"Files",lrFiles);??? return 1;} int main(){??? char* szLua_code=??????? "hFind,sFile = Files.FindFirst('c:////*.*'); "??????? "if hFind then "??????? "??? repeat "??????? "??????? print(sFile) "??????? "??????? sFile = Files.FindNext(hFind) "??????? "??? until sFile==nil; "??????? "??? Files.FindClose(hFind) "??????? "end";??? lua_State *L = luaL_newstate();??? luaL_openlibs(L);??? luaopen_Files(L);???? bool err = luaL_loadstring(L,1);??? }??? lua_close(L);??? return 0;}??? 本例运行结果是显示出C盘根目录下所有的文件名。??? Lua官方建议把函数库写进动态链接库中(windows下.dll文件,linux下.so文件),这样就可以在Lua代码中使用loadlib函数动 态载入函数库例如,我们把上面的例子改成动态链接库版本:DLL代码,假定生成的文件名为fileslib.dll:extern "C" {#include "lua.h"#include "lualib.h"#include "lauxlib.h"}#include <windows.h> BOOL APIENTRY DllMain( HMODULE hModule,?????????????????????? DWORD? ul_reason_for_call,?????????????????????? LPVOID lpReserved???????????????????? ){??? return TRUE;} //函数库示例,Windows下查找文件功能//输入:string路径名//输出:userdata存放Handle(如果没找到,则是nil),NULL}??? /* sentinel */};//导出,注意原型为typedef int (*lua_CFunction) (lua_State *L);extern "C"??? __declspec(dllexport) int luaopen_Files (lua_State *L) {??? luaL_register(L,lrFiles);??? return 1;}Lua调用代码(或者直接使用Lua.exe调用,dll文件必须处于package.cpath指定的目录中,默认与执行文件在同一目录即可):extern "C" {#include "lua.h"#include "lualib.h"#include "lauxlib.h"} #include <iostream>#include <string>#include <windows.h>using namespace std; int main(){??? char* szLua_code=??????? "fileslib = package.loadlib('fileslib.dll','luaopen_Files') "??????? "fileslib() "??????? "hFind,sFile = Files.FindFirst('c:////*.*'); "??????? "if hFind then "??????? "??? repeat "??????? "??????? print(sFile) "??????? "??????? sFile = Files.FindNext(hFind) "??????? "??? until sFile==nil; "??????? "??? Files.FindClose(hFind) "??????? "end";??? lua_State *L = luaL_newstate();??? luaL_openlibs(L);???? bool err = luaL_loadstring(L,1);??? }??? lua_close(L);??? return 0;}Lua代码里使用package.loadlib得到动态链接库中的luaopen_Files函数,然后调用它注册到Lua中,如果动态链接库中的导出 函数名称满足luaopen_<库名>的话,还可以使用require直接载入。比如,如果把本例中的DLL代码里的导出函数名luaopen_Files改成luaopen_fileslib的话,Lua代码便可以改成:char* szLua_code=??????? "require('fileslib') "??????? "hFind,sFile = Files.FindFirst('c:////*.*'); "??????? ...例五,与Lua交换自定义数据??? 由于Lua中的数据类型远不能满足C语言的需要,为此Lua提供了userdata,一个userdata提供了一个在Lua中没有预定义操作的raw内 存区域。??? 在例四的函数库代码中我们已经使用过lightuserdata,它是userdata的一个特例:一个表示C指针的值(也就是一个void *类型的值)。??? 下面的例子我们使用userdata来给Lua提供一个窗体类用于建立,显示窗体。为了简化窗体控制代码,在C函数中我们使用了C++Builder的 VCL库,所以下面的代码要在C++Builder下编译才能通过。当然,稍微修改一下也可以使用MFC,QT,wxWidget等来代替。//---------------------------------------------------------------------------#include <vcl.h>extern "C" {#include "lua.h"#include "lualib.h"#include "lauxlib.h"} #include <iostream>#pragma hdrstop//---------------------------------------------------------------------------#pragma argsused typedef TWinControl* PWinControl;//创建窗体,输入父窗体(或nil),类型,标题//输出创建后的窗体int newCtrl(lua_State *L){??? //input:TWinControl *Parent,type(TForm,TButton,TEdit),text(optional)??? TWinControl *Parent = NULL;??? //从userdata中取得TWinControl*??? if(lua_isuserdata(L,1))??????? Parent = *(PWinControl*)lua_touserdata(L,1);??? String Type = UpperCase(luaL_checkstring(L,2));??? String Text = lua_tostring(L,3);???? TWinControl *R = NULL;???? if(Type == "FORM")??? {??????? R = new TForm(Application);??? }??? else if(Type == "BUTTON")??? {??????? R = new TButton(Application);??? }??? else if(Type == "EDIT")??? {??????? R = new TEdit(Application);??? }??? else??? {??????? luaL_error(L,"unknow type!");??? }???? if(Parent)??????? R->Parent = Parent;???? if(!Text.IsEmpty())??????? ::SetWindowText(R->Handle,Text.c_str());???? //新建userdata,大小为sizeof(PWinControl),用于存放上面生成的窗体指针??? PWinControl* pCtrl = (PWinControl*)lua_newuserdata(L,sizeof(PWinControl));??? *pCtrl = R;??? return 1;} //显示窗体int showCtrl(lua_State *L){??? //input: TWinControl*,for TForm,use ShowModal??? TWinControl* Ctrl = *(PWinControl*)lua_touserdata(L,1);??? TForm *fm = dynamic_cast<TForm*>(Ctrl);??? if(fm)??????? fm->ShowModal();??? else??????? Ctrl->Show();??? return 0;} //定位窗体,输入窗体,左,上,右,下int posCtrl(lua_State *L){??? //input: TWinControl*,Left,Top,Right,Bottom??? TWinControl* Ctrl = *(PWinControl*)lua_touserdata(L,1);??? Ctrl->BoundsRect = TRect(??????? luaL_checkint(L,2),??????? luaL_checkint(L,3),4),5));???? return 0;} //删除窗体int delCtrl(lua_State *L){??? //input: TWinControl*??? TWinControl* Ctrl = *(PWinControl*)lua_touserdata(L,1);??? delete Ctrl;??? return 0;} //把这些函数作为VCL函数库提供给Luastatic const struct luaL_reg lib_VCL [] = {??? {"new",newCtrl},??? {"del",delCtrl},??? {"pos",posCtrl},??? {"show",showCtrl},NULL}}; int luaopen_VCL (lua_State *L) {??? luaL_register(L,"VCL",lib_VCL);??? return 1;} int main(int argc,char* argv[]){??? char* szLua_code=??????? "fm = VCL.new(nil,'Form','Lua Demo'); "??? //新建主窗体fm??????? "VCL.pos(fm,200,500,300); "??????? //定位??????? "edt = VCL.new(fm,'Edit','Hello World'); "? //在fm上建立一个编辑框edt??????? "VCL.pos(edt,5,280,28); "??????? "btn = VCL.new(fm,'Button','Haha'); "??? //在fm上建立一个按钮btn??????? "VCL.pos(btn,100,40,150,63); "??????? "VCL.show(edt); "??????? "VCL.show(btn); "??????? "VCL.show(fm); "?????????????????????? //显示??????? "VCL.del(fm);";???????????????????????? //删除???? lua_State *L = luaL_newstate();??? luaL_openlibs(L);??? luaopen_VCL(L);???? bool err = luaL_loadstring(L,0);??? if(err)??? {??????? std::cerr << lua_tostring(L,1);??? }??????? lua_close(L);??? return 0;}//---------------------------------------------------------------------------使用metatable提供面向对象调用方式??? 上面的VCL代码库为Lua提供了GUI的支持,但是看那些Lua代码,还处于面向过程时期。如何能把VCL.show(edt)之类的代码改成edt: show()这样的形式呢?还是先看代码://---------------------------------------------------------------------------#include <vcl.h>extern "C" {#include "lua.h"#include "lualib.h"#include "lauxlib.h"} #include <iostream>#pragma hdrstop//---------------------------------------------------------------------------#pragma argsused typedef TWinControl* PWinControl;//创建窗体,输入父窗体(或nil),类型,标题//输出创建后的窗体int newCtrl(lua_State *L){??? //input:TWinControl *Parent,text(optional)??? TWinControl *Parent = NULL;???? if(lua_isuserdata(L,1))??????? Parent = *(PWinControl*)luaL_checkudata(L,1,"My_VCL");??? String Type = UpperCase(luaL_checkstring(L,3);???? TWinControl *R = NULL;???? if(Type == "FORM")??????? R = new TForm(Application);??? else if(Type == "BUTTON")??????? R = new TButton(Application);??? else if(Type == "EDIT")??????? R = new TEdit(Application);??? else??????? luaL_error(L,"unknow type!");???? if(Parent)??????? R->Parent = Parent;???? if(!Text.IsEmpty())??????? ::SetWindowText(R->Handle,Text.c_str());???? //output TWinControl*??? PWinControl* pCtrl = (PWinControl*)lua_newuserdata(L,sizeof(PWinControl));??? *pCtrl = R;??? //关联metatable??? luaL_getmetatable(L,"My_VCL");??? lua_setmetatable(L,-2);??? return 1;} //显示窗体int showCtrl(lua_State *L){??? //input: TWinControl*,use ShowModal??? TWinControl* Ctrl = *(PWinControl*)luaL_checkudata(L,"My_VCL");??? TForm *fm = dynamic_cast<TForm*>(Ctrl);??? if(fm)??????? fm->ShowModal();??? else??????? Ctrl->Show();??? return 0;} //定位窗体,输入窗体,左,上,右,下int posCtrl(lua_State *L){??? //input: TWinControl*,Bottom??? TWinControl* Ctrl = *(PWinControl*)luaL_checkudata(L,"My_VCL");??? Ctrl->BoundsRect = TRect(??????? luaL_checkint(L,5));???? return 0;} //删除窗体int delCtrl(lua_State *L){??? //input: TWinControl*??? TWinControl* Ctrl = *(PWinControl*)luaL_checkudata(L,"My_VCL");??? delete Ctrl;??? return 0;} //把这些函数作为VCL函数库提供给Luastatic const struct luaL_reg lib_VCL [] = {??? {"new",NULL}}; int luaopen_VCL (lua_State *L) {??? //建立metatable??? luaL_newmetatable(L,"My_VCL");???? //查找索引,把它指向metatable自身(因为稍后我们会在metatable里加入一些成员)??? lua_pushvalue(L,-1);??? lua_setfield(L,"__index");???? //pos方法??? lua_pushcfunction(L,posCtrl);??? lua_setfield(L,"pos");???? //show方法??? lua_pushcfunction(L,showCtrl);??? lua_setfield(L,"show");???? //析构,如果表里有__gc,Lua的垃圾回收机制会调用它。??? lua_pushcfunction(L,delCtrl);??? lua_setfield(L,"__gc");???? luaL_register(L,char* argv[]){??? char* szLua_code=??????? "local fm = VCL.new(nil,'Lua Demo'); "??? //新建主窗体fm??????? "fm:pos(200,300); "??????? //定位??????? "local edt = VCL.new(fm,'Hello World'); "? //在fm上建立一个编辑框edt??????? "edt:pos(5,28); "??????? "local btn = VCL.new(fm,'Haha'); "??? //在fm上建立一个按钮btn??????? "btn:pos(100,63); "??????? "edt:show(); "??????? "btn:show(); "??????? "fm:show(); ";?????????????????????? //显示??????? //"VCL.del(fm);";?? //不再需要删除了,Lua的垃圾回收在回收userdata地会调用metatable.__gc。???? lua_State *L = luaL_newstate();??? luaL_openlibs(L);??? luaopen_VCL(L);???? bool err = luaL_loadstring(L,1);??? }??????? lua_close(L);??? return 0;}//---------------------------------------------------------------------------我们这儿用到的辅助函数有:int?? luaL_newmetatable (lua_State *L,const char *tname); 对userdata的索引操作就会转向metatable.__index 因为metatable.__index是metatable自身,所以就在这个metatable里查找 这样,对userdata的pos、show索引转到metatable里的pos和show上,它们指向的是我们的C函数posCtrl和 posShow。 最后,当Lua回收这些userdata前,会调用metatable.__gc(如果有的话),我们已经把metatable.__gc指向了C函数 delCtrl。
extern "C" { #include <lua.h> #include <lualib.h> #include <lauxlib.h> } //LuaBind头文件 #include <luabind/luabind.hpp> ?
? // 建立新的Lua环境 ? lua_State *myLuaState = luaL_newstate(); ? ? // 让LuaBind“认识”这个Lua环境 ? luabind::open(myLuaState); ? ? // 定义一个叫add的Lua函数 ? luaL_dostring( ??? myLuaState, ??? "function add(first,second) " ??? "? return first + second " ??? "end " ? ); ?? ? //调用add函数 ? cout << "Result: " ?????? << luabind::call_function<int>(myLuaState,"add",3) ?????? << endl; ? ? lua_close(myLuaState); } ? 在本例中我们先使用Lua C API产生一个Lua线程环境,然后调用luabind::open()让LuaBind关联这个线程环境,在使用LuaBind之前这步是必须做的,它要在Lua环境中注册一些LuaBind专用的数据。在执行完Lua代码之后,我们使用luabind::call_function<int>调用了Lua里的add函数,返回值是int。
? cout << "hello world " << number << endl; } ? int main( ? // 建立新的Lua环境 ? lua_State *myLuaState = lua_open(); ? ? // 让LuaBind“认识”这个Lua环境 ? luabind::open(myLuaState); ? ? // 添加print_hello函数到Lua环境中 ? luabind::module(myLuaState) [ ??? luabind::def("print_hello",print_hello) ? ]; ? ? // 现在Lua中可以调用print_hello了 ? luaL_dostring( ??? myLuaState, ??? "print_hello(123) " ? ); ? ? lua_close(myLuaState); } ? ??? 向Lua环境加入函数或其它东东的方法是:
? public: ??? NumberPrinter(int number) : ????? m_number(number) {} ? ??? void print() { ????? cout << m_number << endl; ??? } ? ? private: ??? int m_number; }; ? int main() { ? lua_State *myLuaState = lua_open(); ? luabind::open(myLuaState); ? ? // 使用LuaBind导出NumberPrinter类 ? luabind::module(myLuaState) [ ??? luabind::class_<NumberPrinter>("NumberPrinter") ????? .def(luabind::constructor<int>()) ????? .def("print",&NumberPrinter::print) ? ]; ? ? // 现在Lua中可以使用NumberPinter类了 ? luaL_dostring( ??? myLuaState, ??? "Print2000 = NumberPrinter(2000) " ??? "Print2000:print() " ? ); ? ? lua_close(myLuaState); } ? 为了注册一个类,LuaBind提供了class_类。它有一个重载过的成员函数 def() 。这个函数被用来注册类的成员函数、操作符、构造器、枚举和属性。它将返回this指针,这样我们就可以方便地直接注册更多的成员。
struct Point { ? Point(T X,T Y) : ??? X(X),Y(Y) {} ? ? T X,Y; }; ? template<typename T> struct Box { ? Box(Point<T> UpperLeft,Point<T> LowerRight) : ??? UpperLeft(UpperLeft),LowerRight(LowerRight) {} ? ? Point<T> UpperLeft,LowerRight; }; ? int main() { ? lua_State *myLuaState = lua_open(); ? luabind::open(myLuaState); ? ? // 使用LuaBind导出Point<float>类和Box<float>类 ? luabind::module(myLuaState) [ ??? luabind::class_<Point<float> >("Point") ????? .def(luabind::constructor<float,float>()) ????? .def_readwrite("X",&Point<float>::X) ????? .def_readwrite("Y",&Point<float>::Y), ? ??? luabind::class_<Box<float> >("Box") ????? .def(luabind::constructor<Point<float>,Point<float> >()) ????? .def_readwrite("UpperLeft",&Box<float>::UpperLeft) ????? .def_readwrite("LowerRight",&Box<float>::LowerRight) ? ]; ? ? // 现在Lua中可以使用为些类了 ? luaL_dostring( ??? myLuaState, ??? "MyBox = Box(Point(10,20),Point(30,40)) " ??? "MyBox.UpperLeft.X = MyBox.LowerRight.Y " ? ); ? ? lua_close(myLuaState); } ? 本例中使用def_readwrite定义类成员,我们也可以用def_readonly把类成员定义成只读。LuaBind还可以把C++类导出成支持getter和setter的属性的Lua类:
? ResourceManager() : ??? m_ResourceCount(0) {} ? ? void loadResource(const string &sFilename) { ??? ++m_ResourceCount; ? } ? size_t getResourceCount() const { ??? return m_ResourceCount; ? } ? ? size_t m_ResourceCount; }; ? int main() { ? lua_State *myLuaState = lua_open(); ? luabind::open(myLuaState); ? ? // 导出类,在Lua中调用ResourceCount属性会调用C++中的ResourceManager::getResourceCount ? // 属性定义有点象C++Builder里的__property定义,呵呵 ? luabind::module(myLuaState) [ ??? luabind::class_<ResourceManager>("ResourceManager") ????? .def("loadResource",&ResourceManager::loadResource) ????? .property("ResourceCount",&ResourceManager::getResourceCount) ? ]; ? ? try { ??? ResourceManager MyResourceManager; ? ??? // 把MyResourceManager定义成Lua的全局变量 ??? luabind::globals(myLuaState)["MyResourceManager"] = &MyResourceManager; ? ??? // 调用 ??? luaL_dostring( ????? myLuaState, ????? "MyResourceManager:loadResource(/"abc.res/") " ????? "MyResourceManager:loadResource(/"xyz.res/") " ????? " " ????? "ResourceCount = MyResourceManager.ResourceCount " ??? ); ? ??? // 读出全局变量 ??? size_t ResourceCount = luabind::object_cast<size_t>( ????? luabind::globals(myLuaState)["ResourceCount"] ??? ); ??? cout << ResourceCount << endl; ? } ? catch(const std::exception &TheError) { ??? cerr << TheError.what() << endl; ? } ? ? lua_close(myLuaState); } ? 附: Lua语法简介
a = "hello"???????????? --string a = false?????????????? --boolean a = {10,"hello",false}? --table a = print?????????????? --function ? ??? 使用type函数可以得到变量当前的类型,如print(type(a));??????? nil???????? 所有没有被赋值过的变量默认值为nil,给变量赋nil可以收回变量的空间。??? boolean???? 取值false和true。但要注意Lua中所有的值都可以作为条件。在控制结构的条件中除了false和nil为假,其他值都为真。所以Lua认为0和空串都是真。(注意,和C不一样哦)??? number????? 表示实数,Lua中没有整数。不用担心实数引起的误差,Lua的numbers可以处理任何长整数。??? string????? 字符串,Lua中的字符串可以存放任何包括0在内的二进制数据。可以使用单引号或双引号表示字符串,和C一样使用/作为转义符。也可以使用或 [[...]]表示字符串,它可以表示多行,而且不解释转义符(也可以是[=[...]=]、[==[]==]、...用于适应各种类型字符串)。另外要注意的是Lua中字符串是不可以修改的。??? function??? 函数,Lua中的函数也可以存储到变量中,可以作为其它函数的参数,可以作为函数的返回值。??? table?????? 表,表是Lua特有的功能强大的东东,它是Lua中唯一的一种数据结构,它可以用来描述数组,结构,map的功能。??? userdata??? userdata类型用来将任意C语言数据保存在Lua变量中。例如:用标准I/O库来描述文件。??? thread????? 线程。由coroutine表创建的一种数据类型,可以实现多线程协同操作。???
??? then-part elseif 条件n then ??? elseif-part ..??????????????? --->多个elseif else ??? else-part end; ? 循环
while a[i] do ??? if a[i] == v then break end ??? i = i + 1 end ? while循环
??? statements; end; ? repeat-until循环:
??? statements; until conditions; ? for循环
??? loop-part end ? ??? for将用exp3作为step从exp1(初始值)到exp2(终止值),执行loop-part。其中exp3可以省略,默认step=1
??? loop-part end ? ??? 实际上,??? for var_1,...,var_n in explist do block end??? 等价于
??? local _f,_s,_var = explist ??? while true do ??????? local var_1,var_n = _f(_s,_var) ??????? _var = var_1 ??????? if _var == nil then break end ??????? block ??? end end ? ??? 如:
for k,v in pairs(a) do print(k,v) end ? 5.函数
??? statements-list; end; ? ??? 函数也可以一次返回多个值,如:
a,c = foo() ? ??? 在Lua中还可以直接定义匿名函数,如??? print((function() return 'a','c' end)())??????? 更详细信息请参考<LUA>/doc/manual.html ?
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |