转载自http://blog.chinaunix.net/uid-571104-id-2734746.html
Lua5.1的常用API
lua_State
Lua状态机或叫Lua虚拟机,支持多线程,可创建多个状态机
typedef int (*lua_Cfunction)(lua_State* L)
Lua所调用的C函数的函数原型,在C程序中需要将这种函数类型的
函数注册到Lua状态机中,此后Lua才能调用到C的函数
如果有函数
int c_Hello(lua_State* l)
{
luaL_checktype(l, 1, LUA_TSTRING)
luaL_checktype(l, 2, LUA_TSTRING) // 两个参数都是字符串
// 先输出第二个参数,后输出第一个参数
printf("%s\t%s\n", lua_tostring(l,-1), lua_tostring(l, -2));
}
需在C程序初始化的时候执行以下代码:
// 将函数名压入LuaVM栈
lua_pushstring(l, "c_hello");
// 将函数地址压入LuaVM栈
lua_pushcclosure(l, &c_Hello, 0)
// 把LuaVM栈上的这个表放入全局表中
lua_settable(l, LUA_GLOBALSINDEX)
此后在Lua中就可以这样调用:
c_hello()
注:C函数的实现如果有参数的话最好为每一个参数进行类型检查
以确保所栈里的参数是函数参数类型匹配
lua_State* lua_newstate(lua_Alloc f, void* ud)
新建一个LuaVM,可以直接调用lua_open来调用这个函数
void lua_close(lua_State* l))
关闭LuaVM
关于栈帧
当一个函数调用发生的时候就形成了一个栈帧,当这个函数调用结束
后这个栈帧就消失了
如在Lua这样调用c_hello("Hello", "World"),那么c_Hello所看到
栈帧就是从它的参数开始,如下图:
可以有两种索引方式对栈顶进行操作,正数和负数。
栈相关操作
int (lua_gettop ) (lua_State *L )
取得当前使用了多少栈空间
void (lua_settop ) (lua_State *L , int idx )
把栈顶设置在idx处,相当于做了一次函数调用改变了栈帧
如果这个时候调用 lua_settop (L , 1 ),则会把刚压入栈的两个参数删除
void (lua_pushvalue ) (lua_State *L , int idx )
向此栈帧的第idx个位置的值压入栈顶,相当于复制
void (lua_remove ) (lua_State *L , int idx )
删除第idx个位置的值
如果lua_remove (L , -2 )则会将 "Hello"删除而剩下 "World"在栈顶
并会被移到原来 "Hello"存放的位置
void (lua_insert ) (lua_State *L , int idx ) ;
先将整个上移或下移,并将栈顶的值压入空出的位置
void (lua_replace ) (lua_State *L , int idx )
把栈顶的值替换掉idx处的值
int (lua_checkstack ) (lua_State *L , int sz )
检查栈的大小是否已经增长到最大值,如果没有则将栈的大小增长sz
返回0表示栈溢出,返回1表示成功
void (lua_xmove ) (lua_State *from , lua_State *to , int n )
从LavVM的栈顶移动n个值到to的LuaVM的栈顶
栈存取操作
以下函数往栈顶压入一个C值
void (lua_pushnil ) (lua_State *L )
往栈顶压入一个NIL值
void (lua_pushnumber ) (lua_State *L , lua_Number n )
往栈顶压入一个实数
void (lua_pushinteger ) (lua_State *L , lua_Integer n )
往栈顶压入一个整数
void (lua_pushlstring ) (lua_State *L , const char *s , size_t l )
往栈顶压入一个二进制串
void (lua_pushstring ) (lua_State *L , const char *s )
往栈顶压入一个字符串
const char * (lua_pushvfstring ) (lua_State *L , const char *fmt , va_list argp )
往栈顶压入一个格式化串,不过argp是变参
const char * (lua_pushfstring ) (lua_State *L , const char *fmt , . . . )
往栈顶压入一个格式化串
void (lua_pushcclosure ) (lua_State *L , lua_CFunction fn , int n )
压入一个函数
void (lua_pushboolean ) (lua_State *L , int b )
往栈顶压入一个bool类型
void (lua_pushlightuserdata ) (lua_State *L , void *p )
往栈顶压入一个数组,数组的内存块指向p
int (lua_pushthread ) (lua_State *L )
以下函数往从栈中复制一个值存入栈顶
void (lua_gettable ) (lua_State *L , int idx )
idx指向表在栈中的位置,弹出栈顶的key取得表中的值并压入栈顶
此函数与lua_rawget的区别在于此函数会调用metatable的方法
void (lua_getfield ) (lua_State *L , int idx , const char *k )
以k所在栈中的索引 (idx )作为参数,取得k对应的值并压入栈顶
效率与lua_gettable相同
void (lua_rawget ) (lua_State *L , int idx )
idx指向表在栈中的位置,弹出栈顶的key取得表中的值并压入栈顶
为了提高数据访问的效率而直接读取表中的数据,不需要对metamethod的调用
这个函数在循环访问数组元素比较方便
void (lua_rawgeti ) (lua_State *L , int idx , int n )
idx指向表在栈中的位置,n指向key在栈中的位置,取得表中的值并入栈
相当于 :lua_pushnumber (L ,n ) ; lua_rawget (L ,idx )
void (lua_createtable ) (lua_State *L , int narr , int nrec )
新建一个表并压入栈顶,表的大小为narr,并预留了nrec个元素空间
void * (lua_newuserdata ) (lua_State *L , size_t sz )
在栈中分配一块大小为sz的内存并把管理结构入栈且返回内存地址
int (lua_getmetatable ) (lua_State *L , int objindex )
objindex指向对象在栈中的位置,取得对象的metatable并将其压入栈顶
如果失败或者对象没有metatable表则返回0
void (lua_getfenv ) (lua_State *L , int idx )
idx指向对象所在栈中的位置,取得此对象并将其环境量压入栈
以下函数用于判断栈内某处值的类型
int (lua_isnumber ) (lua_State *L , int idx )
栈idx处的值是否是实数
int (lua_isstring ) (lua_State *L , int idx )
栈idx处的值是否是字符串
int (lua_iscfunction ) (lua_State *L , int idx )
栈idx处的值是否是函数
int (lua_isuserdata ) (lua_State *L , int idx )
栈idx处的值是否是二进制数据
int (lua_type ) (lua_State *L , int idx )
取得栈idx处的值的类型
const char * (lua_typename ) (lua_State *L , int tp )
将类型转换成C字符串
int (lua_equal ) (lua_State *L , int idx1 , int idx2 )
栈内两个值是否相等,类型和值都需要相等才返回真
int (lua_rawequal ) (lua_State *L , int idx1 , int idx2 )
栈内两个对象是否相等,如果是对象时所指对象相同也算相等
int (lua_lessthan ) (lua_State *L , int idx1 , int idx2 )
栈内两个值的大小 ,idx1处的值是否小于idx2处的值
以下函数将栈内的某个格转换成C能理解的值,栈结构不变
lua_Number (lua_tonumber ) (lua_State *L , int idx )
将idx所指向的Lua值转换成实数返回
lua_Integer (lua_tointeger ) (lua_State *L , int idx )
将idx所指向的Lua值转换成整数返回
int (lua_toboolean ) (lua_State *L , int idx )
将idx所指向的Lua值转换成bool值返回
const char * (lua_tolstring ) (lua_State *L , int idx , size_t *len )
将idx所指向的Lua值转换成字符串返回,并把长度存入len中
size_t (lua_objlen ) (lua_State *L , int idx )
取得idx所指向的Lua值长度
lua_Cfunction (lua_tocfunction ) (lua_State *L , int idx )
将idx所指向的Lua值转换成函数返回
void * (lua_touserdata ) (lua_State *L , int idx )
将idx所指向的Lua值转换成内存块 (数组 )返回
lua_State * (lua_tothread ) (lua_State *L , int idx )
将idx所指向的Lua值转换成LuaVM对象返回
const void * (lua_topointer ) (lua_State *L , int idx )
取得idx所指对象的值的存储地址返回
以下函数与其对应的get函数类似
void (lua_settable ) (lua_State *L , int idx )
void (lua_setfield ) (lua_State *L , int idx , const char *k )
void (lua_rawset ) (lua_State *L , int idx )
void (lua_rawseti ) (lua_State *L , int idx , int n )
int (lua_setmetatable ) (lua_State *L , int objindex )
int (lua_setfenv ) (lua_State *L , int idx )
函数调用
关于函数调用
当需要调用一个Lua函数时,先要将函数压入栈中,然后将其参数依次压入
如下图:
function hello ( x , y )
print ( x , y )
end
则在C中可以这样来调用 :
lua_getglobal (L , "hello" ) ; - - 从全局域中取得hello函数并压入栈顶
lua_pushstring (L , "Hello" ) ; - - 依次压入两个参数
lua_pushstring (L , "World" ) ;
lua_call (L , 2 , 0 ) ; - - 跳过两个参数取得函数并调用此函数 ,函数中会取得相应参数
void (lua_call ) (lua_State *L , int nargs , int nresults )
无保护的函数调用
nargs是指调用函数的参数个数,nresults是指所调用的函数的返回值个数
int (lua_pcall ) (lua_State *L , int nargs , int nresults , int errfunc )
与lua_call相似,不过此函数是在保护模式下被调用
如果发生错误则会将错误压入栈,否则功能与lua_call一样
int (lua_cpcall ) (lua_State *L , lua_CFunction func , void *ud )
直接调用一个C函数,并把ud做为func函数调用的参数
也就是说在func函数内部看来第一个参数是ud
int (lua_load ) (lua_State *L , lua_Reader reader , void *dt , const char *chunkname ) ;