Lua扩展c程序
api
出入栈api
-
push 系列 (C -> Stack)
void lua_pushnil (lua_State * L); void lua_pushboolean (lua_State * L, int bool); void lua_pushnumber (lua_State * L, lua_Number n); // double void lua_pushinteger (lua_State * L, lua_Integer n); // integer void lua_pushlstring (lua_State * L, const char * s, size_t len); void lua_pushstring (lua_State * L, const char * s);
-
set 系列 (Stack -> Lua)
void lua_setglobal(lua_State * L, const char * name); void lua_settable(lua_State * L, int idx); void lua_setfield(lua_State * L, int idx, const char * k); void lua_seti(lua_State * L, int idx, lua_Integer n); void lua_rawset(lua_State * L, int idx); void lua_rawseti(lua_State * L, int idx, lua_Integer n); void lua_rawsetp(lua_State * L, int idx, const void * p); int lua_setmetatable(lua_State * L, int objindex); void lua_setuservalue(lua_State * L, int idx);
-
get 系列 (Lua -> Stack)
int lua_getglobal(lua_State *L, const char *name); int lua_gettable(lua_State *L, int idx); int lua_getfield(lua_State *L, int idx, const char *k); int lua_geti(lua_State *L, int idx, lua_Integer n); int lua_rawget(lua_State *L, int idx); int lua_rawgeti(lua_State *L, int idx, lua_Integer n); int lua_rawgetp(lua_State *L, int idx, const void *p); void lua_createtable(lua_State *L, int narr, int nrec); void* lua_newuserdata(lua_State *L, size_t sz); int lua_getmetatable(lua_State *L, int objindex); int lua_getuservalue(lua_State *L, int idx);
获取栈元素
-
_is 和 _to 系列,不会出栈。
int lua_isnumber(lua_State *L, int idx); int lua_isstring(lua_State *L, int idx); int lua_iscfunction(lua_State *L, int idx); int lua_isinteger(lua_State *L, int idx); int lua_isuserdata(lua_State *L, int idx); int lua_type(lua_State *L, int idx); const char* lua_typename(lua_State *L, int tp); lua_Number lua_tonumberx(lua_State *L, int idx, int *isnum); lua_Integer lua_tointegerx(lua_State *L, int idx, int *isnum); int lua_toboolean(lua_State *L, int idx); const char* lua_tolstring(lua_State *L, int idx, size_t *len); size_t lua_rawlen(lua_State *L, int idx); lua_CFunction lua_tocfunction(lua_State *L, int idx); void* lua_touserdata(lua_State *L, int idx); lua_State* lua_tothread(lua_State *L, int idx); const void* lua_topointer(lua_State *L, int idx);
-
check 系列
// 检查函数的第 arg 个参数是否是一个 数字,并返回这个数字 lua_Number luaL_checknumber(lua_State *L, int arg); // 检查函数的第 arg 个参数是否是一个 字符串并返回这个字符串 const char *luaL_checkstring (lua_State *L, int arg);
栈管理api
-
常用宏函数
// 弹出栈顶 n 个元素 #define lua_pop(L,n) lua_settop(L, -(n) - 1) // 移除栈中索引"index"处的元素, 该元素之上的所有元素下移 #define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) // 将栈顶元素移动到索引"index"处, 索引"index"(含)之上的所有元素上 上移 #define lua_insert(L,idx) lua_rotate(L, (idx), 1)
-
为发防止进栈溢出, 有如下函数可用
int lua_checkstack (lua_State *L, int sz); void luaL_checkstack (lua_State *L, int sz, const char *msg);
-
基本函数
// 返回栈顶元素的索引。因为栈中元素的索引是从 1 开始编号的, 所以函数的返回值相当于栈中元素的个数。返回值为 0 表示栈为空。 int lua_gettop(lua_State *L); //设置栈顶为索引"index"指向处。如果"index"比"lua_gettop()"的值大, 那么多出的新元素将被赋值为"nil"。lua_settop(L, 0); 清空栈。 void lua_settop(lua_State *L, int index); // 将索引"index"处元素, 压到栈顶。(把栈上给定索引处的元素作一个副本压栈) void lua_pushvalue (lua_State *L, int index); // 将栈顶元素拷贝到索引"index"处。(栈顶出栈,覆盖了索引"index"处的元素) void lua_replace(lua_State *L, int index); // 把从 从 idx 开始到栈顶的元素 轮转 n 个位置。 void lua_rotate (lua_State *L, int index, int n);
数据类型宏
-
Lua基本数据类型
#define LUA_TBOOLEAN 1 #define LUA_TLIGHTUSERDATA 2 #define LUA_TNUMBER 3 #define LUA_TSTRING 4 #define LUA_TTABLE 5 #define LUA_TFUNCTION 6 #define LUA_TUSERDATA 7 #define LUA_TTHREAD 8
测试
extern "C"{ #include <lua.h> #include <lualib.h> #include <lauxlib.h> } void stackDump(lua_State *L) { int count = 0; printf("begin dump lua stack %d\n", count); int top = lua_gettop(L); for (int i=1; i <= top; ++i) { int t = lua_type(L, i); switch (t) { case LUA_TSTRING: printf("'%s'\n", lua_tostring(L, i)); break; case LUA_TBOOLEAN: printf(lua_toboolean(L, i) ? "true\n" : "false\n"); break; case LUA_TNUMBER: printf("%g\n", lua_tonumber(L, i)); break; default: printf("%s\n", lua_typename(L, t)); break; } } } int main(int argc, char **argv) { printf("%s\n",argv[0]); lua_State *L = luaL_newstate(); luaL_openlibs(L); stackDump(L); lua_pushinteger(L, 1); lua_pushinteger(L, 2); lua_pushinteger(L, 3); lua_pushinteger(L, 4); stackDump(L); int n = lua_gettop(L); printf("stack size = %d\n", n); //lua_settop(L, 2); //stackDump(L); // lua_pop(L, 1); //lua_pushvalue(L, 2); lua_replace(L, 1); stackDump(L); // lua_rotate(L, 1, -1); lua_insert(L, -2); stackDump(L); luaL_dofile(L, "test.lua"); lua_close(L); return 0; } /* output ./build/main begin dump lua stack 0 begin dump lua stack 0 1 2 3 4 stack size = 4 begin dump lua stack 0 4 2 3 begin dump lua stack 0 4 3 2 test lua... */
Lua扩展C
访问Lua全局变量
int lua_getglobal (lua_State *L, const char *name); // 将 lua 全局作用域中变量名为 name 的成员压入虚拟栈中
测试:
test.lua
price = 9999 name = "kirito"
c
extern "C"{ #include <lua.h> #include <lualib.h> #include <lauxlib.h> } void stackDump(lua_State *L) { int count = 0; printf("begin dump lua stack %d\n", count); int top = lua_gettop(L); for (int i=1; i <= top; ++i) { int t = lua_type(L, i); switch (t) { case LUA_TSTRING: printf("'%s'\n", lua_tostring(L, i)); break; case LUA_TBOOLEAN: printf(lua_toboolean(L, i) ? "true\n" : "false\n"); break; case LUA_TNUMBER: printf("%g\n", lua_tonumber(L, i)); break; default: printf("%s\n", lua_typename(L, t)); break; } } } int main(int argc, char **argv) { lua_State *L = luaL_newstate(); luaL_openlibs(L); int ret = luaL_dofile(L, "test2.lua"); printf("ret = %d\n", ret); lua_getglobal(L, "price"); int price = lua_tointeger(L, -1); printf("price = %d\n", price); lua_getglobal(L, "name"); const char *name = lua_tostring(L, -1); printf("name = %s\n", name); stackDump(L); lua_pop(L, 2); stackDump(L); lua_close(L); return 0; } /* ret = 0 price = 9999 name = kirito begin dump lua stack 0 9999 'kirito' begin dump lua stack 0 */
访问Lua全局表字段
void lua_gettable (lua_State *L, int index); // 把 t[k] 值压入堆栈,这里的 t 是指有效索引 index 指向的值,而 k 则是栈顶放的值。 // 这个函数会弹出堆栈上的 key,把结果放在栈上原来 key 的相同位置。 int lua_getfield (lua_State *L, int index, const char *k); // lua_getfield(stack, -1, "loaded"); // 等 价 于 lua_pushstring(L, "loaded"), lua_gettable(L, -2);
测试:
test.lua
mytab = {price = 9999, name = "kirito"}
c
extern "C"{ #include <lua.h> #include <lualib.h> #include <lauxlib.h> } void stackDump(lua_State *L) { int count = 0; printf("begin dump lua stack %d\n", count); int top = lua_gettop(L); for (int i=1; i <= top; ++i) { int t = lua_type(L, i); switch (t) { case LUA_TSTRING: printf("'%s'\n", lua_tostring(L, i)); break; case LUA_TBOOLEAN: printf(lua_toboolean(L, i) ? "true\n" : "false\n"); break; case LUA_TNUMBER: printf("%g\n", lua_tonumber(L, i)); break; default: printf("%s\n", lua_typename(L, t)); break; } } } int main(int argc, char **argv) { lua_State *L = luaL_newstate(); luaL_openlibs(L); int ret = luaL_dofile(L, "test3.lua"); printf("ret = %d\n", ret); lua_getglobal(L, "mytab"); // lua_pushstring(L, "price"); //-1 -2 // lua_gettable(L, , -2); lua_getfield(L, -1, "price"); int price = lua_tonumber(L, -1); //将 k=price 替换成了 v = 9999 printf("price = %d\n", price); stackDump(L); lua_settop(L, 1); lua_getfield(L, -1, "name"); const char *name = lua_tostring(L, -1); printf("name = %s\n", name); stackDump(L); lua_pop(L, 2); stackDump(L); lua_close(L); return 0; } /* ret = 0 price = 9999 begin dump lua stack 0 table 9999 name = kirito begin dump lua stack 0 table 'kirito' begin dump lua stack 0 */
访问Lua全局函数
int luaL_dofile (lua_State *L, const char *filename); // 加载并运行文件 是个宏定义 // luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET,0) int luaL_loadfile (lua_State *L, const char *filename); // 调用 load 函数,加载文件并编译文件为 lua 的 chunk,然后将其推到栈顶。 int lua_load(lua_State *L, lua_Reader reader, void *data, const char *chunkname, const char *mode); // 加载一段 Lua 代码块,但不运行它。 如果没有错误, lua_load 把一个编译好的代码 // 块作为一个 Lua 函数压到栈顶。 否则,压入错误消息。 int lua_pcall (lua_State *L, int nargs, int nresults, int msgh); // 安全模式下的,lua_call。通常,最后一个参数填零 // if msgh == 0 then the error object returned on the stack is exactly the original error object void lua_call (lua_State *L, int nargs, int nresults); // 要想调用一个 lua 函数,流程如下, // 第一,函数必须被压栈 // 第二,依次序压入参数,调用 lua_call,nargs 是入栈参数的个数。 // 第三,函数调用后,函数及其参数要出栈, // 第四,返回值入栈,入栈顺序,先入栈者底,后入栈者顶,nresults 填入返回值的个数。
测试:
test.lua
function myfunc( name, a, b) return "my name is "..name , a+b end
c
extern "C"{ #include <lua.h> #include <lualib.h> #include <lauxlib.h> } void stackDump(lua_State *L) { int count = 0; printf("begin dump lua stack %d\n", count); int top = lua_gettop(L); for (int i=1; i <= top; ++i) { int t = lua_type(L, i); switch (t) { case LUA_TSTRING: printf("'%s'\n", lua_tostring(L, i)); break; case LUA_TBOOLEAN: printf(lua_toboolean(L, i) ? "true\n" : "false\n"); break; case LUA_TNUMBER: printf("%g\n", lua_tonumber(L, i)); break; default: printf("%s\n", lua_typename(L, t)); break; } } } int main(int argc, char **argv) { lua_State *L = luaL_newstate(); luaL_openlibs(L); int ret = luaL_dofile(L, "test4.lua"); printf("ret = %d\n", ret); lua_getglobal(L, "myfunc"); lua_pushstring(L, "kirito"); lua_pushinteger(L, 1); lua_pushnumber(L, 3.14); stackDump(L); lua_pcall(L, 3, 2, 0); const char * name = lua_tostring(L, -2); double a = lua_tonumber(L, -1); stackDump(L); printf("return %s, %lf\n", name, a); lua_close(L); return 0; } /* ret = 0 begin dump lua stack 0 function 'kirito' 1 3.14 begin dump lua stack 0 'my name is kirito' 4.14 return my name is kirito, 4.140000 */
C扩展Lua
Lua可以调用C的函数,必须先注册注册函数,即以一种恰当的方式为Lua提供C函数的地址。
Lua调用C函数时,也使用了一个与C调用Lua函数时相同类型的栈,C函数从栈中获取参数,并将结果压入栈。注意此处栈不是一个全局的栈,每个函数都用私有局部栈,Lua调用C时,第一个参数总是位于局部栈索引1的位置,栈底
无论何时 Lua 调用 C, 被调用的函数都得到一个 新的栈,这个栈于 独立于 C 函数本身
的栈,也独立于之前的 Lua 栈。它里面包含了 Lua 传递给 C 函数的所有参数,而 C 函
数则把要返回的结果放入这个栈以返回给调用者。
Lua访问C入栈的值
api
void lua_setglobal (lua_State *L, const char *name); // 将虚拟栈中,将栈顶元素弹出,作为全局 lua 变量 name 的值。 void lua_newtable (lua_State *L); // 产生一个空表, 并推入栈 void lua_settable (lua_State *L, int index); // 作一个等价于 t[k] = v 的操作,这里 t 是一个给定有效索引 index 处的值,v 指栈顶的值,而 k 是栈顶之下的那个值。 // 把栈顶作为 value,栈顶的下一个作为 key 设置到 index 指向的 table,最后把这两个全部弹出栈,这时候 settable 完成。 // lua_pushstring(L, "name"); // lua_pushstring(L, "123"); // lua_settable(L, -3); void lua_setfield (lua_State *L, int index, const char *k); // 等价于 t[k] = v,t 是栈上索引为 index 的表,v 是栈顶的值。函数结束,栈顶值v 会被弹出。 // lua_pushstring(L, "name"); // lua_pushstring(L, "123"); // lua_settable(L, -3); // 等价于 // lua_pushstring(L,"123"); //此两句,可顶上三句 // lua_setfield(L, -2, "name");
测试:
test.lua
print("in lua ...") print(name) print(price) print(t.name) print(t.price)
c
extern "C"{ #include <lua.h> #include <lualib.h> #include <lauxlib.h> } void stackDump(lua_State *L) { int count = 0; printf("begin dump lua stack %d\n", count); int top = lua_gettop(L); for (int i=1; i <= top; ++i) { int t = lua_type(L, i); switch (t) { case LUA_TSTRING: printf("'%s'\n", lua_tostring(L, i)); break; case LUA_TBOOLEAN: printf(lua_toboolean(L, i) ? "true\n" : "false\n"); break; case LUA_TNUMBER: printf("%g\n", lua_tonumber(L, i)); break; default: printf("%s\n", lua_typename(L, t)); break; } } } int main(int argc, char **argv) { lua_State *L = luaL_newstate(); luaL_openlibs(L); int price = 9999; const char *name = "kirito"; lua_pushnumber(L, price); lua_setglobal(L, "price"); stackDump(L); lua_pushstring(L, name); lua_setglobal(L, "name"); stackDump(L); lua_newtable(L); lua_pushstring(L, "price"); lua_pushinteger(L, 100); lua_settable(L, -3); lua_pushstring(L,"kirito"); //此两句,可顶上三句 lua_setfield(L, -2, "name"); lua_setglobal(L, "t"); stackDump(L); int ret = luaL_dofile(L, "test5.lua"); printf("ret = %d\n", ret); lua_close(L); return 0; } /* begin dump lua stack 0 begin dump lua stack 0 begin dump lua stack 0 in lua ... kirito 9999.0 kirito 100 ret = 0 */
Lua调用C函数
api
typedef int (*lua_CFunction) (lua_State *L); void lua_pushcfunction (lua_State *L, n lua_CFunction f); // 将函数压入栈,该函数接受一个 C 类型的函数指针,并将其以 lua function 形式入栈。 // 在 lua 中调用该函数即会发生 c 函数的调用。 int foo(lua_State *L) { int n = lua_gettop(L); // 栈顶idx,就是参数个数 int sum = 0; for (int i=1; i<=n; ++i) { if (!lua_isnumber(L,i)) { lua_pushliteral(L, "incorrect argument"); lua_error(L); // 返回 } sum += lua_tonumber(L,i); } lua_pushnumber(L, sum/n); lua_pushnumber(L, sum); return 2; // 返回值个数 } void lua_register (lua_State *L, const char *name, lua_CFunction f); // 其本质等同于先 pushcfunction,然后再 setglobal。
测试:
test.lua
a, b = foo(1,2,3,4); print(a) print(b)
c
extern "C"{ #include <lua.h> #include <lualib.h> #include <lauxlib.h> } void stackDump(lua_State *L) { int count = 0; printf("begin dump lua stack %d\n", count); int top = lua_gettop(L); for (int i=1; i <= top; ++i) { int t = lua_type(L, i); switch (t) { case LUA_TSTRING: printf("'%s'\n", lua_tostring(L, i)); break; case LUA_TBOOLEAN: printf(lua_toboolean(L, i) ? "true\n" : "false\n"); break; case LUA_TNUMBER: printf("%g\n", lua_tonumber(L, i)); break; default: printf("%s\n", lua_typename(L, t)); break; } } } int func_return_table(lua_State *L) { lua_newtable(L); //创建一个表格, 放在栈顶 lua_pushstring(L, "key"); //压入 key lua_pushnumber(L, 66); //压入 value lua_settable(L, -3); //弹出 key, value, 并设置到 table 里面去 lua_pushstring(L,"foo"); lua_pushcfunction(L,foo); lua_settable(L, -3); // return 1; } int foo(lua_State *L) { int n = lua_gettop(L); // 栈顶idx,就是参数个数 int sum = 0; for (int i=1; i<=n; ++i) { if (!lua_isnumber(L,i)) { lua_pushliteral(L, "incorrect argument"); lua_error(L); } sum += lua_tonumber(L,i); } lua_pushnumber(L, sum/n); lua_pushnumber(L, sum); return 2; // 返回值个数 } int main(int argc, char **argv) { lua_State *L = luaL_newstate(); luaL_openlibs(L); lua_register(L, "foo", foo); int ret = luaL_dofile(L, "test6.lua"); printf("ret = %d\n", ret); lua_close(L); return 0; } /* 2.0 10.0 ret = 0 */
c函数批量注册
api
typedef struct luaL_Reg { const char *name; lua_CFunction func; } luaL_Reg; // 用于存放,函数指针和注册的函数名。常用于生成数组,数组的最后一个元素,一定是以{NULL,NULL}结尾 // 等价于 luaL_newlibtable(L,l),luaL_setfuncs(L,l,0) void luaL_newlib (lua_State *L, const luaL_Reg l[]); // luaL_newlib 也是一个宏函数,简化了创建表和循环注册函数 void luaL_newlibtable (lua_State *L, const luaL_Reg l[]); // 创建一张新的表,并预分配足够保存下数组 l 内容的空间(但不填充) void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); // 设置数组 l 中所有函数的到栈顶的表中 第三个参数通常为 0 void luaL_requiref (lua_State *L, const char *modname, lua_CFunction openf, int glb); // 如果 modname 不在 package.loaded 中,则调用 openf 函数以 modname 为参数,使其为 package.loaded[modname]。其行为类似于 require,如果 glb 为 true,则存储模块到全局的 modname。
测试:
test.lua
print(my.add(1,2)) print(my.foo(1,2))
c
extern "C"{ #include <lua.h> #include <lualib.h> #include <lauxlib.h> } void stackDump(lua_State *L) { int count = 0; printf("begin dump lua stack %d\n", count); int top = lua_gettop(L); for (int i=1; i <= top; ++i) { int t = lua_type(L, i); switch (t) { case LUA_TSTRING: printf("'%s'\n", lua_tostring(L, i)); break; case LUA_TBOOLEAN: printf(lua_toboolean(L, i) ? "true\n" : "false\n"); break; case LUA_TNUMBER: printf("%g\n", lua_tonumber(L, i)); break; default: printf("%s\n", lua_typename(L, t)); break; } } } int foo(lua_State *L) { int n = lua_gettop(L); // 栈顶idx,就是参数个数 int sum = 0; for (int i=1; i<=n; ++i) { if (!lua_isnumber(L,i)) { lua_pushliteral(L, "incorrect argument"); lua_error(L); } sum += lua_tonumber(L,i); } lua_pushnumber(L, sum/n); lua_pushnumber(L, sum); return 2; // 返回值个数 } int add(lua_State *L) { int n = lua_gettop(L); int sum = 0; for (int i=0; i<n; ++i) { sum+=lua_tonumber(L, i+1); } if (n!=0) { lua_pushnumber(L, sum); return 1; } return 0; } const luaL_Reg lib[] = { {"foo", foo}, {"add", add}, {NULL,NULL} }; int luaopen_my(lua_State *L) { luaL_newlib(L, lib); return 1; } int main(int argc, char **argv) { lua_State *L = luaL_newstate(); luaL_openlibs(L); // 统一注册lua中调用的函数 luaL_requiref(L, "my", luaopen_my, 1); stackDump(L); int ret = luaL_dofile(L, "test7.lua"); printf("ret = %d\n", ret); lua_close(L); return 0; } /* begin dump lua stack 0 table 3.0 1.0 3.0 ret = 0 */
c++生成dll/so
c
extern "C"{ #include <lua.h> #include <lualib.h> #include <lauxlib.h> } int foo(lua_State *L) { int n = lua_gettop(L); // 栈顶idx,就是参数个数 int sum = 0; for (int i=1; i<=n; ++i) { if (!lua_isnumber(L,i)) { lua_pushliteral(L, "incorrect argument"); lua_error(L); } sum += lua_tonumber(L,i); } lua_pushnumber(L, sum/n); lua_pushnumber(L, sum); return 2; // 返回值个数 } int add(lua_State *L) { int n = lua_gettop(L); int sum = 0; for (int i=0; i<n; ++i) { sum+=lua_tonumber(L, i+1); } if (n!=0) { lua_pushnumber(L, sum); return 1; } return 0; } const luaL_Reg lib[] = { {"foo", foo}, {"add", add}, {NULL,NULL} }; extern "C"{ // luaopen_xx xx必须和最后生成库的名字一致 比如 my.so luaopen_my int luaopen_my(lua_State *L) { luaL_newlib(L, lib); return 1; } }
lua
-- 动态库名字改成my.so my=require("my") print(my.add(1,2)) print(my.foo(1,2))
Lua
环境安装
- 官网 www.lua.org
$ curl -LO http://www.lua.org/ftp/lua-5.3.5.tar.gz $ tar -xzf lua-5.3.5.tar.gz $ cd lua-5.3.5/ # 依赖 libreadline-dev $ make linux test $ sudo make install $ lua -v # 检查
简介
数据类型
类型 | 描述 |
---|---|
nil | 无效值 |
boolean | false与true |
number | 相当于double |
string | 'str' 或者"str" |
function | C或Lua函数 |
userdata | 存储在变量中的C数据结构 |
thread | 协程 |
table | 关联数组 |
语法
-- 注释 --[[ 多行注释 ]] print("Hello World") --[[关键词 and break do else elseif end false for function if in local nil not or repeat return then true until while goto 一般约定,以下划线开头连接一串大写字母的名字(比如 _VERSION)被保留用于 Lua 内部全局变量。 ]] print(type("Hello world")) --> string print(type(10.4*3)) --> number print(type(print)) --> function print(type(type)) --> function print(type(true)) --> boolean print(type(nil)) --> nil print(type(type(X))) --> string -- 给全局变量或者 table 表里的变量赋一个 nil 值,等同于把它们删掉 tab1 = { key1 = "val1", key2 = "val2", "val3" } for k, v in pairs(tab1) do print(k .. " - " .. v) end type(X)=="nil" -- 作比较应该加双引号 -- false 和 nil 看作是 false,其他的都为 true,数字 0 也是 true if false or nil then print("至少有一个是 true") else print("false 和 nil 都为 false") end -- 可以用方括号表示一块字符串 str = [[ 123 124 ]] -- 在对一个数字字符串上进行算术操作时,Lua 会尝试将这个数字字符串转成一个数字 -- 字符串连接使用的是 .. print("str" .. 1) -- str1 print(123 .. 123) -- 123123 数值连接 -- 使用 # 来计算字符串的长度 str = "123" print(#str) print(#"123") -- local 局部变量 省略为全局变量 local tab = {} local tbl2 = {"apple", "pear", "orange", "grape"} -- 默认初始索引一般以1开始 function factorial1(n) if n == 0 then return 1 else return n * factorial1(n - 1) end end factorial2 = factorial1 -- 赋值 x = 1 x, y = y, x a, b = f() -- f可以多参返回,返回少了就是nil -- 对于table t[i] t.i -- 当索引为字符串类型时的一种简化写法 gettable_event(t,i) -- 采用索引访问本质上是一个类似这样的函数调用
循环
while( a < 20 ) do print("a 的值为:", a) a = a+1 end -- var 从 exp1 变化到 exp2,每次变化以 exp3 为步长递增 var,并执行一次 "执行体"。exp3 是可选的,如果不指定,默认为1。 for var=exp1,exp2,exp3 do <执行体> end for i=1,f(x) do print(i) end for i=10,1,-1 do print(i) end a = {"one", "two", "three"} for i, v in ipairs(a) do print(i, v) end repeat print("a的值为:", a) a = a + 1 until( a > 15 )
流程控制
--[ 0 为 true ] if(0) then print("0 为 true") end if( a == 10 ) then print("a 的值为 10" ) elseif( a == 20 ) then print("a 的值为 20" ) elseif( a == 30 ) then print("a 的值为 30" ) else print("没有匹配 a 的值" ) end print("a 的真实值为: ", a )
函数
local function max(num1, num2) if (num1 > num2) then result = num1; else result = num2; end return result; end function maximum (a) local mi = 1 -- 最大值索引 local m = a[mi] -- 最大值 for i,val in ipairs(a) do if val > m then mi = i m = val end end return m, mi end print(maximum({8,10,23,12,5})) -- 可变参 function add(...) -- select("#",...) 来获取可变参数的数量 print("总共传入 " .. select("#",...) .. " 个数") local s = 0 for i, v in ipairs{...} do --> {...} 表示一个由所有变长参数构成的数组 s = s + v end return s end print(add(3,4,5,6,7)) --->25 function fwrite(fmt, ...) ---> 固定的参数fmt return io.write(string.format(fmt, ...)) end function foo(...) for i = 1, select('#', ...) do -->获取参数总数 local arg = select(i, ...); -->读取参数 print("arg", arg); end end foo(1, 2, 3, 4);
运算符
+ - * / % ^(乘幂) == ~= > < >= <= and or not ..(连接符 两个点!) #(一元运算符,返回字符串或表的长度)
数组
-- 初始化多维数组 array = {} for i=1,3 do array[i] = {} for j=1,3 do array[i][j] = i*j end end -- 访问数组 for i=1,3 do for j=1,3 do print(array[i][j]) end end
迭代器
-- 泛型 for 迭代器 -- 泛型 for 在自己内部保存迭代函数,实际上它保存三个值:迭代函数、状态常量、控制变量。 for k, v in pairs(t) do print(k, v) end -- 使用了 Lua 默认提供的迭代函数 ipairs array = {"Google", "Runoob"} for key,value in ipairs(array) do print(key, value) end -- 无状态的迭代器 function square(iteratorMaxCount,currentNumber) if currentNumber<iteratorMaxCount then currentNumber = currentNumber+1 return currentNumber, currentNumber*currentNumber end end -- 泛型 for 需要三个值:迭代函数、状态常量、控制变量 -- 对于 for 结构来说,状态常量没有用处,仅初始化用 for i,n in square,3,0 do print(i,n) end function iter (a, i) i = i + 1 local v = a[i] if v then return i, v end end function ipairs (a) return iter, a, 0 end -- 多状态的迭代器 array = {"Google", "Runoob"} function elementIterator (collection) local index = 0 local count = #collection -- 闭包函数 return function () index = index + 1 if index <= count then -- 返回迭代器的当前元素 return collection[index] end end end for element in elementIterator(array) do print(element) end
模块与包
-- 文件名为 module.lua -- 定义一个名为 module 的模块 module = {} -- 定义一个常量 module.constant = "这是一个常量" -- 定义一个函数 function module.func1() io.write("这是一个公有函数!\n") end local function func2() print("这是一个私有函数!") end function module.func3() func2() end return module --------------------------------------使用包 -- test_module.lua 文件 -- module 模块为上文提到到 module.lua module = require("module") print(module.constant) module.func3() --[[ 对于自定义的模块,模块文件不是放在哪个文件目录都行,函数 require 有它自己的文件路径加载策略,它会尝试从 Lua 文件或 C 程序库中加载模块。 require 用于搜索 Lua 文件的路径是存放在全局变量 package.path 中,当 Lua 启动后,会以环境变量 LUA_PATH 的值来初始这个环境变量。如果没有找到该环境变量,则使用一个编译时定义的默认路径来初始化。 #LUA_PATH export LUA_PATH="~/lua/?.lua;;" 文件路径以 ";" 号分隔,最后的 2 个 ";;" 表示新加的路径后面加上原来的默认路径。 ]] -----c 包 local path = "/usr/local/lua/lib/libluasocket.so" local f = loadlib(path, "luaopen_socket") local path = "/usr/local/lua/lib/libluasocket.so" -- 或者 path = "C:\\windows\\luasocket.dll",这是 Window 平台下 local f = assert(loadlib(path, "luaopen_socket")) f() -- 真正打开库
协程
方法 | 描述 |
---|---|
coroutine.create() | 创建 coroutine,返回 coroutine, 参数是一个函数,当和 resume 配合使用的时候就唤醒函数调用 |
coroutine.resume() | 重启 coroutine,和 create 配合使用 |
coroutine.yield() | 挂起 coroutine,将 coroutine 设置为挂起状态,这个和 resume 配合使用能有很多有用的效果 |
coroutine.status() | 查看 coroutine 的状态 注:coroutine 的状态有三种:dead,suspended,running,具体什么时候有这样的状态请参考下面的程序 |
coroutine.wrap() | 创建 coroutine,返回一个函数,一旦你调用这个函数,就进入 coroutine,和 create 功能重复 |
coroutine.running() | 返回正在跑的 coroutine,一个 coroutine 就是一个线程,当使用running的时候,就是返回一个 corouting 的线程号 |
来源:https://www.cnblogs.com/kirito1/p/12642976.html