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

Lua与C/C++的交互

发布时间:2020-12-14 22:15:37 所属栏目:大数据 来源:网络整理
导读:转载自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

转载自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*?l)
?? ? ? ? ? ?{
?? ? ? ? ? ? ? luaL_checktype(l,?1)
?? ? ? ? ? ? ? luaL_checktype)????//?两个参数都是字符串
????????????????/?先输出第二个参数,后输出第一个参数
???????????? printf("%st%sn"-1-2;
      }

????????????需在C程序初始化的时候执行以下代码:
????????????????????/?将函数名压入LuaVM栈
????????????????????lua_pushstring"c_hello";
????????????????????/?将函数地址压入LuaVM栈
????????????????????lua_pushcclosure&c_Hello)
????????????????????/?把LuaVM栈上的这个表放入全局表中
????????????????????lua_settable)
????????????此后在Lua中就可以这样调用:
????????????????????c_hello)

????????????注:C函数的实现如果有参数的话最好为每一个参数进行类型检查
????????????????????以确保所栈里的参数是函数参数类型匹配

????lua_State*?lua_newstate(lua_Alloc f*?ud)
????????????新建一个LuaVM
????void lua_close)
????????????关闭LuaVM


????关于栈帧
????????????当一个函数调用发生的时候就形成了一个栈帧,当这个函数调用结束
????????????后这个栈帧就消失了

????????????如在Lua这样调用c_hello"Hello""World"),那么c_Hello所看到
????????????栈帧就是从它的参数开始,如下图:
????????????可以有两种索引方式对栈顶进行操作,正数和负数。????



????栈相关操作
???????????? int? (lua_gettop )? (lua_State? *L )
????????????????????取得当前使用了多少栈空间
????????????void? (lua_settop int?idx )
????????????????????把栈顶设置在idx处,相当于做了一次函数调用改变了栈帧
????????????????????如果这个时候调用 lua_settop (L ),则会把刚压入栈的两个参数删除
????????????void? (lua_pushvalue )
????????????????????向此栈帧的第idx个位置的值压入栈顶,相当于复制
????????????void? (lua_remove )
????????????????????删除第idx个位置的值
????????????????????如果lua_remove -2 )则会将 "Hello"删除而剩下 "World"在栈顶
????????????????????并会被移到原来 "Hello"存放的位置
????????????void? (lua_insert ) ;
????????????????????先将整个上移或下移,并将栈顶的值压入空出的位置
????????????void? (lua_replace )
????????????????????把栈顶的值替换掉idx处的值
???????????? (lua_checkstack int?sz )
????????????????????检查栈的大小是否已经增长到最大值,如果没有则将栈的大小增长sz
????????????????????返回0表示栈溢出,返回1表示成功
????????????void? (lua_xmove *from *to int?n )
????????????????????从LavVM的栈顶移动n个值到to的LuaVM的栈顶


????栈存取操作
????????????以下函数往栈顶压入一个C值
????????????void? (lua_pushnil )
????????????????????往栈顶压入一个NIL值
????????????void? (lua_pushnumber )
????????????????????往栈顶压入一个实数
????????????void? (lua_pushinteger )
????????????????????往栈顶压入一个整数
????????????void? (lua_pushlstring *s )
????????????????????往栈顶压入一个二进制串
????????????void? (lua_pushstring )
????????????????????往栈顶压入一个字符串
????????????const char? * (lua_pushvfstring *fmt )
????????????????????往栈顶压入一个格式化串,不过argp是变参
????????????const char? (lua_pushfstring . )
????????????????????往栈顶压入一个格式化串
????????????void? (lua_pushcclosure )
????????????????????压入一个函数
????????????void? (lua_pushboolean int?b )
????????????????????往栈顶压入一个bool类型
????????????void? (lua_pushlightuserdata *p )
????????????????????往栈顶压入一个数组,数组的内存块指向p
???????????? (lua_pushthread )


????????????以下函数往从栈中复制一个值存入栈顶
????????????void? (lua_gettable )
????????????????????idx指向表在栈中的位置,弹出栈顶的key取得表中的值并压入栈顶
????????????????????此函数与lua_rawget的区别在于此函数会调用metatable的方法
????????????void? (lua_getfield *k )
????????????????????以k所在栈中的索引 (idx )作为参数,取得k对应的值并压入栈顶
????????????????????效率与lua_gettable相同
????????????void? (lua_rawget )
????????????????????idx指向表在栈中的位置,弹出栈顶的key取得表中的值并压入栈顶
????????????????????为了提高数据访问的效率而直接读取表中的数据,不需要对metamethod的调用
????????????????????这个函数在循环访问数组元素比较方便
????????????void? (lua_rawgeti )
????????????????????idx指向表在栈中的位置,n指向key在栈中的位置,取得表中的值并入栈
????????????????????相当于 :lua_pushnumber ;?lua_rawget )
????????????void? (lua_createtable int?narr int?nrec )
????????????????????新建一个表并压入栈顶,表的大小为narr,并预留了nrec个元素空间
????????????void? (lua_newuserdata )
????????????????????在栈中分配一块大小为sz的内存并把管理结构入栈且返回内存地址
???????????? (lua_getmetatable int?objindex )
????????????????????objindex指向对象在栈中的位置,取得对象的metatable并将其压入栈顶
????????????????????如果失败或者对象没有metatable表则返回0
????????????void? (lua_getfenv )
????????????????????idx指向对象所在栈中的位置,取得此对象并将其环境量压入栈

????????????以下函数用于判断栈内某处值的类型
???????????? (lua_isnumber )
????????????????????栈idx处的值是否是实数
???????????? (lua_isstring )
????????????????????栈idx处的值是否是字符串
???????????? (lua_iscfunction )
????????????????????栈idx处的值是否是函数
???????????? (lua_isuserdata )
????????????????????栈idx处的值是否是二进制数据
???????????? (lua_type )
????????????????????取得栈idx处的值的类型
????????????const char? (lua_typename int?tp )
????????????????????将类型转换成C字符串
???????????? (lua_equal int?idx1 int?idx2 )
????????????????????栈内两个值是否相等,类型和值都需要相等才返回真
???????????? (lua_rawequal )
????????????????????栈内两个对象是否相等,如果是对象时所指对象相同也算相等
???????????? (lua_lessthan )
????????????????????栈内两个值的大小
????????????以下函数将栈内的某个格转换成C能理解的值,栈结构不变
????????????lua_Number? (lua_tonumber )
????????????????????将idx所指向的Lua值转换成实数返回
????????????lua_Integer? (lua_tointeger )
????????????????????将idx所指向的Lua值转换成整数返回
???????????? (lua_toboolean )
????????????????????将idx所指向的Lua值转换成bool值返回
????????????const char? (lua_tolstring *len )
????????????????????将idx所指向的Lua值转换成字符串返回,并把长度存入len中
????????????size_t? (lua_objlen )
????????????????????取得idx所指向的Lua值长度
????????????lua_Cfunction? (lua_tocfunction )
????????????????????将idx所指向的Lua值转换成函数返回
????????????void? (lua_touserdata )
????????????????????将idx所指向的Lua值转换成内存块 (数组 )返回
????????????lua_State? (lua_tothread )
????????????????????将idx所指向的Lua值转换成LuaVM对象返回
????????????const void? (lua_topointer )
????????????????????取得idx所指对象的值的存储地址返回

????????????以下函数与其对应的get函数类似
????????????void? (lua_settable (lua_setfield (lua_rawset (lua_rawseti )
???????????? (lua_setmetatable (lua_setfenv )

????函数调用
????  关于函数调用
????????  当需要调用一个Lua函数时,先要将函数压入栈中,然后将其参数依次压入
?? ? ? ? ? ?如下图:

?? ? ? ? ? ? 假设在Lua代码中有函数 :
?? ? ? ? ? ? ? ?function hello ( x )
?? ? ? ? ? ? ? ?   print )
?? ? ? ? ? ? ? ?end
?? ? ? ? ? ? ? ?则在C中可以这样来调用 :
?????????????? lua_getglobal "hello" ;? - -?从全局域中取得hello函数并压入栈顶
?? ? ? ? ? ? ? ?lua_pushstring "Hello" ;  -?依次压入两个参数
?????????????? lua_pushstring "World" ;????
?? ? ? ? ? ? ? ?lua_call ?0 -?跳过两个参数取得函数并调用此函数 ????????????????????????????????????
????????????void? (lua_call int?nargs int?nresults )
????????????????????无保护的函数调用
????????????????????nargs是指调用函数的参数个数,nresults是指所调用的函数的返回值个数
???????????? (lua_pcall int?errfunc )
????????????????????与lua_call相似,不过此函数是在保护模式下被调用
????????????????????如果发生错误则会将错误压入栈,否则功能与lua_call一样
???????????? (lua_cpcall *ud )
????????????????????直接调用一个C函数,并把ud做为func函数调用的参数
????????????????????也就是说在func函数内部看来第一个参数是ud
???????????? (lua_load *dt *chunkname ;

(编辑:李大同)

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

    推荐文章
      热点阅读