一、Lua加入工程
1)官方下载源码,解压;
2)使用VS或XCode或其他IDE新建一个“hello worde”的C++工程;
3)将lua源码加入工程目录中,我的测试目录结构如下,
1 2 3 4 5 6 7 ├── lua │ ├── Makefile │ ├── README │ ├── doc │ └── src ├── main.cpp └── main.lua
./lua即为lua源码包解压出来的东西,lua的源码文件在lua/src目录下,将lua/src下的文件除Makefile、lua.c(有一个main函数,这是lua的解释器) 、luac.c(lua编译器,编译后的lua脚本可被更高效率的使用) 外的其他源码文件都加入到helloworld的工程中,当然,可以在工程中增加一个”luasrc”的文件筛选器,将要加入的lua源码文件都放在该文件筛选器下,便于工程结构的分类管理。 此时在main.cpp中,还未加入lua的引用,先编译一次,应该可以编译通过main.cpp及lua的源码文件。
示例main.cpp,再编译一次,应该可以编译成功,示例程序MyLua可用来执行指定的lua脚本的文件。
二、变量 全局(虚拟机对多文件全局)
就理解为是lua_State的全局变量x,对所有文件都通用。
本地(虚拟机对单文件局部)(local关键字修饰)
就理解为是lua_State在某个文件里的变量y,仅在那个文件中可用。
三、变量与类型 Lua是动态类型语言,变量不要类型定义,只需要为变量赋值,给变量赋值了什么类型,变量就是什么类型。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 local boolean bv = 0.0 bv = x > 250 if bv then print ("bv is " , bv, " true" ) else print ("bv is " , bv, " false" ) end math .randomseed (os .time ()) bv = math .random (500 ) if bv > 250 then print ("bv is " , bv, " > 250" ) else print ("bv is " , bv, " <= 250" ) end bv = "bv -> string" print ("bv is " , bv)bv = "0xEF" print ("bv is " , bv)print (type (bv)) bv = bv + 1 print ("bv is " , bv)print (type (bv)) bv = "0xEF" print ("bv is " , bv)bv = string .format ("%s%s" , bv, "kkkl" ) print ("bv is " , bv)print (type (bv)) bv = "0xEF" print ("bv is " , bv)print (type (bv)) bv = string .format ("%d%s" , bv, "kkkl" ) print ("bv is " , bv)print (type (bv))
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 bv is false false bv is 231 <= 250 bv is bv -> string bv is 0xEF string bv is 240.0 number bv is 0xEF bv is 0xEFkkkl string bv is 0xEF string bv is 239kkkl string
四、控制语句 if判断 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 math .randomseed (os .time ()) x = math .random (500 ) print ("x is" , x)if x < 100 then print ("x ∈ [0, 100)" ) elseif x < 200 then print ("x ∈ [100, 200)" ) elseif x == 250 then print ("中彩票了,250" ) elseif x < 300 then print ("x ∈ [200, 250)U(250, 300)" ) elseif x < 400 then print ("x ∈ [300, 400)" ) elseif x < 500 then print ("x ∈ [400, 500)" ) elseif x == 500 then print ("x == 500" ) else print ("x is " , x) end
for循环 1 2 3 for i = 0 , 1 , 0.1 do print ("for: i is" , i) end
while循环 1 2 3 4 5 i = 1.1 while i < 2 do print ("while: i is " , i) i = i + 0.1 end
repeat循环 1 2 3 4 5 i = 2.0 repeat print ("repeat: i is " , i) i = i + 0.1 until i > 3
五、表、元表、元方法 万能的表,表之于LUA的地位应该就相当于类之于C++了吧,之前在理解元表与元方法上还有许多模糊的地方。看视频教材,也没有说的很清楚,遂决定抛弃视频教材,还是看看官方的手册比较靠谱点。
表、元表、元方法的关系简单理解应该就是,元表中定义了元方法,或者说元方法就是元表的元素,表使用setmetatable关联元表,表就可以调用元表中的元方法了,而元表的本质也还是表,所以任意表都可以做元表,包括表做自己的元表,可见元表应该是一个相对的概念。
剩下需要重点学习一下的就是元方法了。
操作符”重载”的元方法 1 2 3 4 5 6 7 8 9 10 11 12 __add __sub __mul __div __unm __mod __pow __call __eq __lt __le
库定义的元方法
table访问/赋值的元方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 Set = {} local mt = {}mt.name = "defaultName" function Set.new (l) local set = {} setmetatable (set, mt) for k, v in ipairs (l) do set[v] = true end return set end function Set.union (a, b) local res = Set.new{} for k in pairs (a) do res[k] = true end for k in pairs (b) do res[k] = true end return res end function Set.intersection (a, b) local res = Set.new{} for k in pairs (a) do res[k] = b[k] end return res end function Set.tostring (set) local l = {} for k in pairs (set) do l[#l + 1 ] = k end return "{" .. table .concat (l, ", " ) .. "}" end function Set.print (s) print (Set.tostring (s)) end s1 = Set.new{10 , 20 , 30 , 50 } s2 = Set.new{30 , 1 } print (mt)print ("s1的元表" , getmetatable (s1))print ("s2的元表" , getmetatable (s2))Set.print (s1) Set.print (s2) mt.__add = Set.union Set.print (s1 + s2) mt.__mul = Set.intersection Set.print ((s1+s2)*s1) mt.__le = function (a, b) for k in pairs (a) do if not b[k] then return false end end return true end mt.__lt = function (a, b) return a <= b and not (b <= a) end mt.__eq = function (a, b) return a <= b and b <= a end print (s1 < s2, s2 > s1)print (s1 <= s2, s2 >= s1)print (s1 == s2)print (s1*s2 <= s1+s2)print (s1*s2 < s1+s2)mt.__tostring = Set.tostring print (s1, s2, s1+s2, s1*s2)mt.__metatable = "not your business" print (getmetatable (s1)) mt.__index = mt s1.name = "s1 table" s2.name = "s2 table" print (s1.name, s2.name)print (s2.name, s1.name)
六、类 实际lua中应该没有类的概念,而是使用原型的概念来组织对象间的共享行为。原型也是一种常规对象,当其他对象遇到未知操作时就在这个对象的原型对象中寻找这个未知操作的定义。这样元表的作用就和原型的作用很类似,所以就可以使用元表来实现lua的面向对象编程,原型也就成了元表在lua面向对象编程时的代名词。
继承和多重继承 使用setmetatable(Super, Base)和Base.__index = Base来模拟继承的特性。
使用setmetatable(Super, {__index = function (t, k) return search(k, {Base1, Base2}); end})来模拟多重继承的特性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 Account = {balance = 0 }; function Account:new (o) o = o or {}; setmetatable (o, self); self.__index = self; return o; end function Account:deposit (v) self.balance = self.balance + v; print ("deposit" , self.balance); end function Account:withdraw (v) if v > self.balance then print ("insufficient funds" ); end self.balance = self.balance - v; print ("withdraw" , self.balance); end SpecialAccount = Account:new(); function SpecialAccount:getLimit () return self.limit or 0 ; end function SpecialAccount:withdraw (v) if self.balance - v < -self:getLimit() then print ("insufficient funds" ); end self.balance = self.balance - v; print ("withdraw" , self.balance); end a3 = Account:new{balance = 0 }; a4 = Account:new(); s1 = SpecialAccount:new{limit = 1000.00 }; s2 = SpecialAccount:new(); print (Account, a1, a2, a3, a4, getmetatable (a4), getmetatable (s1));print (Account, a1, a2, a3, a4, getmetatable (a4), getmetatable (s1));a3:withdraw(100 ); a4:withdraw(100 ); s1:withdraw(100 ); s2:withdraw(100 ); Named = {} function Named:getName () return self.name; end function Named:setName (n) self.name = n; end local function search (k, plist) for i, z in pairs (plist) do local v = plist[i][k] if v then return v end end end function createClass (a, b) local c = {} local parents = {a, b} setmetatable (c, {__index = function (t, k) return search(k, parents); end }) c.__index = c; function c:new (o) o = o or {}; setmetatable (o, self); return o; end return c; end NamedAccount = createClass(Account, Named); SpecialNamedAccount = createClass(SpecialAccount, Named); acnt1 = NamedAccount:new{name = "Paul" }; acnt2 = SpecialNamedAccount:new{name = "Ann" }; print (acnt1:getName(), acnt1.balance);acnt2:deposit(200 ); print (acnt2:getName(), acnt2.balance, acnt2:getLimit());
私密性 虽然可以模拟,但对lua的设计目的而言,私密性似乎不非常重要,暂时一瞥掠过。
七、与C/C++交互 C程序可以使用lua库来执行lua代码,lua代码也可以调用在lua环境中注册了的用C语言实现的函数。 lua的C API包含读写lua全局变量、调用lua函数、运行一段lua代码、注册C函数供lua调用等。 lua.h(lua.hpp)声明了Lua提供的基础函数,包括创建Lua环境、调用Lua函数、读写Lua环境中的全局变量以及注册供lua调用的函数等,函数都以lua_开头; luaxlib.h声明了辅助库(auxiliary library,auxlib)提供的函数,都以luaL_开头。辅助库并没有直接访问Lua的内部,而是都以官方基础API来完成所有工作。 Lua库中没有定义任何全局变量,而是将所有的状态信息都保存在动态结构lua_State中,所有lua C API的调用都要传入这个动态结构的指针。如果简单的将lua_State看作栈的话,这个栈有可以看作有两套引索序号,一套是从栈底到栈顶依次是1到N递增(绝对引索),另一套是从栈顶到栈底的引索序号-1到-N的递减(相对引索)。所以可以直接使用引索值-1和1分别访问栈顶和栈底元素。
环境创建 lua_State是C程序与lua交互编程中最常用的数据结构,要C程序读取Lua中的变量,也是先调用lua的CAPI,将lua中的数据压入lua_State栈中,然后C程序再通过lua的CAPI读取lua_State栈中的元素,如此间接读取到lua的变量值。
1 2 3 LUALIB_API lua_State *(luaL_newstate) (void ); LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, const luaL_Reg *l, int nup) ;LUALIB_API void (luaL_openlibs) (lua_State *L) ;
压元素入栈(增) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 LUA_API void (lua_pushnil) (lua_State *L) ;LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n) ;LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n) ;LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len); LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, va_list argp); LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n) ;LUA_API void (lua_pushboolean) (lua_State *L, int b) ;LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p) ;LUA_API int (lua_pushthread) (lua_State *L) ;#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) #define lua_pushliteral(L, s) lua_pushstring(L, "" s) #define lua_pushglobaltable(L) lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) LUA_API int (lua_checkstack) (lua_State *L, int n) ;
访问栈元素(查) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 LUA_API int (lua_isnumber) (lua_State *L, int idx) ;LUA_API int (lua_isstring) (lua_State *L, int idx) ;LUA_API int (lua_iscfunction) (lua_State *L, int idx) ;LUA_API int (lua_isinteger) (lua_State *L, int idx) ;LUA_API int (lua_isuserdata) (lua_State *L, int idx) ;LUA_API int (lua_type) (lua_State *L, int idx) ;LUA_API const char *(lua_typename) (lua_State *L, int tp); #define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) #define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) #define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) #define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) #define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) #define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) #define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) #define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum) ;LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum) ;LUA_API int (lua_toboolean) (lua_State *L, int idx) ;LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); LUA_API size_t (lua_rawlen) (lua_State *L, int idx) ;LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx) ;LUA_API void *(lua_touserdata) (lua_State *L, int idx); LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); LUA_API const void *(lua_topointer) (lua_State *L, int idx); #define lua_tostring(L,i) lua_tolstring(L, (i), NULL) #define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL) #define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL)
其他栈元素操作 1 2 3 4 5 6 7 LUA_API int (lua_gettop) (lua_State *L) ; LUA_API void (lua_settop) (lua_State *L, int idx) ; LUA_API void (lua_pushvalue) (lua_State *L, int idx) ; #define lua_pop(L,n) lua_settop(L, -(n)-1) #define lua_insert(L,idx) lua_rotate(L, (idx), 1) #define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) #define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1))
执行lua程序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) ;#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k) ;LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k) ;#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) #define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode) ;LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip) ;#define luaL_dofile(L, fn) (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) #define luaL_dostring(L, s) (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
lua扩展应用程序 参数配置 lua中定义一些全局变量,应用程序调用api将lua中的全局变量值压到L栈中,再通过api从L栈中将该值读取出来,即到读取配置参数的目的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 void luaStackDump (lua_State *L) { for (int i = lua_gettop(L); i > 0 ; i--) { int iType = lua_type(L, i); switch (iType) { case LUA_TSTRING: case LUA_TBOOLEAN: case LUA_TNUMBER: case LUA_TNIL: { cout << "(" << lua_typename(L, iType) << ")" << lua_tostring(L, i) << endl ; } break ; default : { cout << "(" << lua_typename(L, iType) << ")" << endl ; } break ; } } } void error (lua_State *L, const char *fmt, ...) { va_list argp; va_start(argp, fmt); vfprintf (stderr , fmt, argp); va_end(argp); luaStackDump(L); lua_close(L); printf ("app exit." ); exit (1 ); } void luaGetGlobalInt (lua_State *L, const string &strVarName, int &iRet) { lua_getglobal(L, strVarName.c_str()); if (!lua_isnumber(L, -1 )) { error(L, "'%s' should be a number\n" , strVarName.c_str()); } iRet = (int )lua_tointeger(L, -1 ); lua_pop(L, 1 ); cout << strVarName << " is " << iRet << endl ; } void luaGetTableFiledValue (lua_State *L, const string &strTblName, const string &strFldName, string &strValue) { lua_getglobal(L, strTblName.c_str()); if (!lua_istable(L, -1 )) { error(L, "%s is not a table\n" , strTblName.c_str()); } lua_pushstring(L, strFldName.c_str()); lua_gettable(L, -2 ); strValue = lua_tostring(L, -1 ); lua_pop(L, 2 ); cout << strTblName << "[" << strFldName << "] is " << strValue << endl ; } void luaGetTableFiledValue (lua_State *L, const string &strTblName, const vector <string > &vctstrFldsName, vector <string > &vctstrValues) { lua_getglobal(L, strTblName.c_str()); if (!lua_istable(L, -1 )) { error(L, "%s is not a table\n" , strTblName.c_str()); } for (unsigned int i = 0 ; i < vctstrFldsName.size(); i++) { lua_pushstring(L, vctstrFldsName[i].c_str()); lua_gettable(L, -2 ); vctstrValues.push_back(lua_tostring(L, -1 )); lua_pop(L, 1 ); } lua_pop(L, 1 ); }
C/C++程序调用lua脚本 lua中定义好函数后,C代码中使用api获取lua的函数对象压入到L栈中,然后再向L栈中按顺序压入函数参数,然后调用lua_pcall指定函数调用的参数个数和返回值个数,lua_pcall调用后,将会将之前压入的L栈的函数对象与参数弹出,然后将函数执行的返回值或函数执行失败的错误信息压入L栈中。C代码通过API从栈中将返回值或错误信息读取出来,然后需要C代码调用调用lua_pop里显示清理栈,恢复L栈至函数调用前状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 void luaCallLuaFunc (lua_State *L, const string &strFuncName, const vector <string > &vctstrParams, vector <string > &vctstrRets) { lua_getglobal(L, strFuncName.c_str()); for (unsigned int i = 0 ; i < vctstrParams.size(); i++) { lua_pushstring(L, vctstrParams[i].c_str()); } if (lua_pcall(L, vctstrParams.size(), vctstrRets.size(), NULL ) != 0 ) { error(L, "error running function getSize: %s\n" , lua_tostring(L, -1 )); } for (int i = vctstrRets.size() - 1 ; i >= 0 ; i--) { vctstrRets[i] = lua_tostring(L, -1 ); lua_pop(L, 1 ); } cout << "call " << strFuncName << "(" ; if (vctstrParams.size() > 0 ) { cout << "\"" << vctstrParams[0 ] << "\"" ; for (unsigned int i = 1 ; i < vctstrParams.size(); i++) { cout << ", \"" << vctstrParams[i] << "\"" ; } } cout << ") returns (" ; if (vctstrRets.size() > 0 ) { cout << "\"" << vctstrRets[0 ] << "\"" ; for (unsigned int i = 1 ; i < vctstrRets.size(); i++) { cout << ", \"" << vctstrRets[i] << "\"" ; } } cout << ")" << endl ; } void luaCallLuaFunc2 (lua_State *L, const char *cfunc, const char *cfrm, ...) { va_list vl; int narg = 0 ; int nres = 0 ; va_start(vl, cfrm); lua_getglobal(L, cfunc); for (narg = 0 ; *cfrm != '\0' ; narg++) { luaL_checkstack(L, 1 , "too many arguments" ); switch (*cfrm++) { case 'f' : { lua_pushnumber(L, va_arg(vl, const double )); } break ; case 'd' : { lua_pushinteger(L, va_arg(vl, const int )); } break ; case 's' : { lua_pushstring(L, va_arg(vl, const char *)); } break ; case '>' : { goto endargs; } break ; default : { error(L, "invalid option (%c)" , *(cfrm - 1 )); } break ; } } endargs: int irescnt = nres = strlen (cfrm); if (lua_pcall(L, narg, nres, 0 ) != 0 ) { error(L, "error calling %s:%s" , cfunc, lua_tostring(L, -1 )); } nres = -nres; while (*cfrm) { switch (*cfrm++) { case 'f' : { if (!lua_isnumber(L, nres)) { error(L, "wrong result type" ); } *va_arg(vl, double *) = lua_tonumber(L, nres); } break ; case 'd' : { if (!lua_isinteger(L, nres)) { error(L, "wrong result type" ); } *va_arg(vl, int *) = (int )lua_tointeger(L, nres); } break ; case 's' : { if (!lua_isstring(L, nres)) { error(L, "wrong result type" ); } *va_arg(vl, const char **) = lua_tostring(L, nres); } break ; default : { error(L, "invalid option (%c)" , *(cfrm-1 )); } break ; } nres++; } lua_pop(L, irescnt); va_end(vl); }
lua脚本调用C/C++ lua脚本调用C/C++函数 所有注册到lua中的函数都具有相同的类型,或者可以说只有一种特定类型的函数才能注册到lua中, 该函数类型lua.h中定义如下
1 typedef int (*lua_CFunction) (lua_State *L) ;
通过使用lua_pushcfunction和lua_setglobal两个方法就可以将一个函数注册到lua中,然后就可以在lua中通过使用lua_setglobal设置的globalname来调用到这个C函数了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 void registCFuncToLua (lua_State *L, lua_CFunction pfunc, const string &strGlobalName) { lua_pushcfunction(L, pfunc); lua_setglobal(L, strGlobalName.c_str()); } static int l_sin (lua_State *L) { double dbl = luaL_checknumber(L, 1 ); lua_pushnumber(L, sin (dbl)); return 1 ; } int main () { ... registCFuncToLua(L, l_sin, "c_sin" ); ... }
使用C/C++定义LUA模块 以下LUA调用C/C++的方法应该可以理解成require "libname"语句的实现原理吧,简单理解就是在将C/C++代码封装成动态库时,若需要生成的动态库可以被lua require后使用,就需要在该动态库中定义一个接口(一个数组+一个函数);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 static int l_f1 (lua_State *L) { ... } static int l_f2 (lua_State *L) { ... } ... static const luaL_Reg mylib[] = { {"f1" , l_f1}, {"f2" , l_f2}, ... {NULL , NULL } }; int luaopen_mylib (lua_State *L) { luaL_register(L, "mylib" , mylib); return 1 ; }