微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Lua笔记

注册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指向的栈上的一个
ottom:0px; padding:0px; white-space:pre-wrap; word-wrap:break-word; font-size:13px; line-height:19.5px; background-color:rgb(254,栈顶元素是(Stack[index])[k]
注意,该操作将触发 __index 元方法
3. 给表中的元素赋值
void lua_setfield (lua_State *L,242)">操作:   arr = Stack[index]
        arr[k] = Stack.top()
        Stack.pop()
给表中键为k的元素赋值value(value就是栈顶元素),242)">栈高度-1,被弹出的是value
ottom:0px; padding:0px; white-space:pre-wrap; word-wrap:break-word; font-size:13px; line-height:19.5px; background-color:rgb(254,该操作将触发 __newindex 元方法
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.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐