一般我们用 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);
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);
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))
没有返回值
栈不变化