加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Lua笔记

发布时间:2020-12-14 21:57:13 所属栏目:大数据 来源:网络整理
导读:注册c函数 一般我们用 luaL_register,比如 lua_register(L,? "testfunc" ,?testf); 其中testf就是c函数,这样lua就可以调用了 我们还可以批量注册函数 static luaL_Reg mylibs[] = { { " add " ,add}, { sub {NULL,NULL} }; luaL_register(L,"mylib",mylibs

注册c函数

一般我们用 luaL_register,比如lua_register(L,?"testfunc",?testf); 其中testf就是c函数,这样lua就可以调用了

我们还可以批量注册函数

static luaL_Reg mylibs[] = { 
     {"add",add},     {sub    {NULL,NULL} 
}; 
luaL_register(L,"mylib",mylibs);
这样在lua里面就可以调用,注意调用的时候要加上名字,比如 mylib.add


栈操作相关函数

?1). 压入元素:lua_push*
?? ?Lua针对每种C类型,都有一个C API函数与之对应,如:

? ? void lua_pushnumber(lua_State* L,lua_Number n);?--浮点数
?? ?void lua_pushlstring(lua_State* L,const char* s,size_t len);?--指定长度的内存数据
?? ?void lua_pushstring(lua_State* L,const char* s);??--以零结尾的字符串,其长度可由strlen得出。
?? ?对于字符串数据,Lua不会持有他们的指针,而是调用在API时生成一个内部副本,因此,即使在这些函数返回后立刻释放或修改这些字符串指针,也不会有任何问题。
?? ?在向栈中压入数据时,可以通过调用下面的函数判断是否有足够的栈空间可用,一般而言,Lua会预留20个槽位,对于普通应用来说已经足够了,除非是遇到有很多参数的函数。
?? ?int lua_checkstack(lua_State* L,int extra)?--期望得到extra数量的空闲槽位,如果不能扩展并获得,返回false。?
?? ?
?? ?2). 查询元素:int lua_is* (lua_State *L,int index);,比如
?? ?int lua_islightuserdata (lua_State *L,int index);
?? ?int lua_isnumber (lua_State *L,255)">?? ?int lua_isuserdata (lua_State *L,sans-serif; line-height:18px">?? ?以上函数,成功返回1,否则返回0。需要特别指出的是,对于lua_isnumber而言,不会检查值是否为数字类型,而是检查值是否能转换为数字类型。
?? ?Lua还提供了一个函数lua_type,用于获取元素的类型,函数原型如下:
?? ?int lua_type (lua_State *L,sans-serif; line-height:18px">?? ?该函数的返回值为一组常量值,分别是:LUA_TNIL、LUA_TNUMBER、LUA_TBOOLEAN、LUA_TSTRING、LUA_TTABLE、LUA_TFUNCTION、LUA_TUSERDATA、LUA_TTHREAD和LUA_TLIGHTUSERDATA

? ??
? ? 3)转换函数,ua_to* (lua_State *L,int index),如:
?? ?int lua_toboolean (lua_State *L,int index);

? ? 查询和转换函数都不会将元素从堆栈里面抛出

? ?4)其它函数
? ?lua_getglobal(lua_State* L,char* name) 从lua的全局表里面取出名字为name的值,这个函数其实是一个宏定义,#define lua_getglobal(L,s) lua_getfield(L,LUA_GLOBALSINDEX,(s)),c++先把name压栈,然后lua从栈中抛出这个name,取值压栈,就是说调用之后是name对应的值在栈顶,需要我们通过lua_to*函数取出来

?lua_setglobal则是设置lua中的全局变量值

? ? int lua_gettop(lua_State* L);?--返回栈中元素的个数。
?? ?void lua_settop(lua_State* L,int index);?--将栈顶设置为指定的索引值。
?? ?void lua_pushvalue(lua_State* L,0)">--将指定索引的元素副本压入栈。
?? ?void lua_remove(lua_State* L,0)">--删除指定索引上的元素,其上面的元素自动下移。
?? ?void lua_insert(lua_State* L,0)">--将栈顶元素插入到该索引值指向的位置。

?? ?void lua_replace(lua_State* L,0)">--弹出栈顶元素,并将该值设置到指定索引上。

? ? ?lua_pop(L,n) 抛出栈顶的n个元素


5)通过堆栈对表的操作

??void lua_getfield(lua_State *L,int idx,const char *k); 第二个参数是table变量在栈中的索引值,最后一个参数是table的键值,该函数执行成功后会将字段值压入栈中。
????void lua_setfield(lua_State *L,const char *k);?第二个参数是table变量在栈中的索引值,最后一个参数是table的键名称,而字段值是通过上一条命令压入到栈中的,该函数在执行成功后会将刚刚压入的字段值弹出栈


? ? 读取表,先通过lua_getglobal得到表,然后获取表里面的元素比如lua里面有一张表 tbtest = { mem1=5,mem2=7.9}

? ?lua_getglobal(L,"tbltest"); //这时候tbltest已经放在栈顶了

? lua_getfield(L,-1,"mem1");// 这样就把 mem1的值放入到栈顶了

? int nmem1 = lua_tointeger(L,-1);

? lua_pop(L,1); //这样tbltest又回到栈顶了

? double dbmem2 = lua_tonumber(L,-1);

??

表的操作

1.? 建一个新表

void lua_createtable (lua_State *L,int narr,int nrec)
创建一个新的table,并把它放在栈顶. narr和nrec分别指定该table的array部分和hash部分的预分配元素数量
无返回值
栈高度+1,栈顶元素是新table
#define lua_newtable(L) lua_createtable(L,0) 常用这个
?
2. 取表中的元素
void lua_getfield (lua_State *L,int index,const char *k)
操作:   arr = Stack[index]    // arr肯定是表
        Stack.push( arr[k] )
取表中键为k的元素,这里的表是由index指向的栈上的一个表
注意,该操作将触发 __index 元方法
3. 给表中的元素赋值
void lua_setfield (lua_State *L,242)">操作:   arr = Stack[index]
        arr[k] = Stack.top()
        Stack.pop()
给表中键为k的元素赋值value(value就是栈顶元素),242)">栈高度-1,被弹出的是value
4. 取表元素 和 表元素赋值
void lua_gettable (lua_State *L,int index)

操作:???? ele? = Stack[index]

??????????? key = Stack.top()

??????????? Stack.pop()

??????????? value = ele[key]

??????????? Stack.push(value)

根据index指定取到相应的表; 取栈顶元素为key,并弹出栈; 获取表中key的值压入栈顶.

无返回值

栈高度不变,但是发生了一次弹出和压入的操作,弹出的是key,压入的是value

注意,该操作将触发 __index 元方法

?

void lua_settable (lua_State *L,int index)
操作:   ele    = Stack[index]
        value  = Stack.top()
        key    = Stack.top()
        ele[key] = value
根据index指定取到相应的表; 取栈顶元素做value,弹出之; 再取当前栈顶元素做key,亦弹出之; 然后将表的键为key的元素赋值为value
栈高度-2,第一次弹出value,第二次弹出key
5. 对table的一些操作[不引发原方法]
void lua_rawget (lua_State *L,242)"> 和lua_gettable操作一样

但是不触发相应的元方法

??

void lua_rawgeti(lua_State *L,int n)

操作:?? ele = Stack[index]

??????? value = ele[n]

??????? Stack.push(value)

无返回值

栈+1, 栈顶新增元素就是 value

不触发相应的元方法

??

void lua_rawset (lua_State *L,int index) 

和lua_settable操作一样

?但是不触发相应的原方法

void lua_rawseti (lua_State *L,int n)

??????? value = Stack.top()

??????? Stack.pop()

??????? ele[n] = value

栈-1,栈顶将value弹出

?

6. 复制栈上元素并压入栈

void lua_pushvalue (lua_State *L,242)"> 操作:?? value = Stack[index]???????

?????? Stack.push(value)

栈+1?

7. 创建一个元表

int luaL_newmetatable (lua_State *L,const char *tname)

操作:?? 1. 在注册表中查找tname,如果已经注册,就返回0,否者继续,并平栈

??????? lua_getfield(L,LUA_REGISTRYINDEX,tname)

??????? if (!lua_isnil(L,-1))

??????????? return 0;

??????? lua_pop(L,1);

??????? 2. 创建一个表,并注册,返回1

??????? lua_newtable(L)

??????? lua_pushvalue(L,-1)

??????? lua_setfield(L,242)"> ??????? return 1

有返回值
栈+1,栈顶元素是在注册表中注册过的新表
8. 创建C值
void *lua_newuserdata (lua_State *L,size_t size)

该函数分配一块由size指定大小的内存块,并放在栈顶

返回值是新分配的块的地址

栈+1, 栈顶是userdata

userdata用来在lua中表示c中的值. 一个完整的userdata有自己的元表,在垃圾回收时,可以调用它的元表的__gc方法

9. 注册c函数到lua中,其实没有这回事,lua中只有c闭包

void lua_pushcclosure (lua_State *L,lua_CFunction fn,int n)

向栈上压一个C闭包

当一个c函数被创建时,可以绑定几个值在它上面,从而形成一个闭包.? 在任何时刻调用这个c函数时,都可以访问这几个绑定值.?

绑定的方法: 先一次压入要绑定的n个值到栈上,然后调用lua_pushcclosure(L,fn,n)这样就形成的一个c闭包

栈 –(n - 1),一共弹出n个元素(及那些绑定的值),压入一个cclosure

#define lua_pushcfunction(L,f) lua_pushcclosure(L,f,0)

#define lua_register(L,n,f) (lua_pushcfunction(L,f),lua_setglobal(L,n))

没有返回值

栈不变化

这个是比较常用的,以n为lua中的key压入一个0个绑定值的cclosure.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读