﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-xylyan-随笔分类-Lua</title><link>http://www.cppblog.com/xylyan/category/19490.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 11 Jun 2012 13:44:09 GMT</lastBuildDate><pubDate>Mon, 11 Jun 2012 13:44:09 GMT</pubDate><ttl>60</ttl><item><title>[转]lua和c/c++互相调用实例分析 </title><link>http://www.cppblog.com/xylyan/archive/2012/05/03/173600.html</link><dc:creator>意吟</dc:creator><author>意吟</author><pubDate>Thu, 03 May 2012 11:29:00 GMT</pubDate><guid>http://www.cppblog.com/xylyan/archive/2012/05/03/173600.html</guid><wfw:comment>http://www.cppblog.com/xylyan/comments/173600.html</wfw:comment><comments>http://www.cppblog.com/xylyan/archive/2012/05/03/173600.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/xylyan/comments/commentRss/173600.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/xylyan/services/trackbacks/173600.html</trackback:ping><description><![CDATA[lua作为小巧精悍的脚本语言，易于嵌入c/c++中 ， 广泛应用于游戏AI ，实际上在任何经常变化的逻辑上都可以使用lua实现，配合c/c++实现的底层接口服务，能够大大降低系统的维护成本。下面对lua和c/c++的交互调用做一个实例分析：<br />lua提供了API用于在c/c++中构造lua的运行环境，相关接口如下：<br />//创建lua运行上下文<br />lua_State* luaL_newstate(void) ;<br />//加载lua脚本文件<br />int luaL_loadfile(lua_State *L, const char *filename);<br /><br />lua和c/c++的数据交互通过"栈"进行 ,操作数据时，首先将数据拷贝到"栈"上，然后获取数据，栈中的每个数据通过索引值进行定位，索引值为正时表示相对于栈底的偏移索引，索引值为负时表示相对于栈顶的偏移索引，索引值以1或-1为起始值，因此栈顶索引值永远为-1 ,栈底索引值永远为1 。 "栈"相当于数据在lua和c/c++之间的中转地。每种数据都有相应的存取接口 。<br />数据入"栈"接口：<br />void (lua_pushnil) (lua_State *L);<br />void (lua_pushnumber) (lua_State *L, lua_Number n);<br />void (lua_pushinteger) (lua_State *L, lua_Integer n);<br />void (lua_pushlstring) (lua_State *L, const char *s, size_t l);<br />void (lua_pushstring) (lua_State *L, const char *s);<br />void (lua_pushboolean) (lua_State *L, int b);<br />void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);<br /><br />数据获取接口：<br />lua_Number (lua_tonumber) (lua_State *L, int idx);<br />lua_Integer (lua_tointeger) (lua_State *L, int idx);<br />int (lua_toboolean) (lua_State *L, int idx);<br />const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);<br />lua_CFunction (lua_tocfunction) (lua_State *L, int idx);<br /><br /><br />"栈"操作接口：<br />int (lua_gettop) (lua_State *L);<br />void (lua_settop) (lua_State *L, int idx);<br />void (lua_pushvalue) (lua_State *L, int idx);<br />void (lua_remove) (lua_State *L, int idx);<br />void (lua_insert) (lua_State *L, int idx);<br />void (lua_replace) (lua_State *L, int idx);<br />int (lua_checkstack) (lua_State *L, int sz);<br /><br />lua中定义的变量和函数存放在一个全局table中，索引值为LUA_GLOBALSINDEX ，table相关操作接口：<br />void (lua_gettable) (lua_State *L, int idx);<br />void (lua_getfield) (lua_State *L, int idx, const char *k);<br />void (lua_settable) (lua_State *L, int idx);<br />void (lua_setfield) (lua_State *L, int idx, const char *k);<br /><br />当"栈"中包含执行脚本需要的所有要素(函数名和参数)后，调用lua_pcall执行脚本：<br />int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);<br /><br />下面进行实例说明：<br />func.lua<br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">--变量定义<br />width</span><span style="color: #000000">=</span><span style="color: #000000">1</span><span style="color: #000000"> ;<br />height</span><span style="color: #000000">=</span><span style="color: #000000">2</span><span style="color: #000000"> ;<br />--lua函数定义，实现加法<br />function sum(a,b)<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;return</span><span style="color: #000000"> a</span><span style="color: #000000">+</span><span style="color: #000000">b ;<br />end<br />--lua函数定义，实现字符串相加<br />function mystrcat(a,b)<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;return</span><span style="color: #000000"> a..b ;<br />end<br />--lua函数定义，通过调用c代码中的csum函数实现加法<br />function mysum(a,b)<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;return</span><span style="color: #000000"> csum(a,b) ;<br />end</span></div><br />test_lua.c<br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">#include </span><span style="color: #000000">&lt;</span><span style="color: #000000">stdio.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include </span><span style="color: #000000">&lt;</span><span style="color: #000000">stdlib.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include </span><span style="color: #000000">&lt;</span><span style="color: #0000ff">string</span><span style="color: #000000">.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #000000">#include </span><span style="color: #000000">&lt;</span><span style="color: #000000">errno.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span>//lua头文件<br /><span style="color: #000000">#include </span><span style="color: #000000">&lt;</span><span style="color: #000000">lua.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include </span><span style="color: #000000">&lt;</span><span style="color: #000000">lualib.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include </span><span style="color: #000000">&lt;</span><span style="color: #000000">lauxlib.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #000000"><br /><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000"> err_exit(num,fmt,args<img alt="" src="http://www.cppblog.com/Images/dot.gif" />) \</span><span style="color: #000000"><br /></span><span style="color: #0000ff">do</span><span style="color: #000000">{printf(</span><span style="color: #000000">"</span><span style="color: #000000">[%s:%d]</span><span style="color: #000000">"</span><span style="color: #000000">fmt</span><span style="color: #000000">"</span><span style="color: #000000">\n</span><span style="color: #000000">"</span><span style="color: #000000">,__FILE__,__LINE__,##args);exit(num);} </span><span style="color: #0000ff">while</span><span style="color: #000000">(</span><span style="color: #000000">0</span><span style="color: #000000">)<br /></span><span style="color: #0000ff">#define</span><span style="color: #000000"> err_return(num,fmt,args<img alt="" src="http://www.cppblog.com/Images/dot.gif" />) \</span><span style="color: #000000"><br /></span><span style="color: #0000ff">do</span><span style="color: #000000">{printf(</span><span style="color: #000000">"</span><span style="color: #000000">[%s:%d]</span><span style="color: #000000">"</span><span style="color: #000000">fmt</span><span style="color: #000000">"</span><span style="color: #000000">\n</span><span style="color: #000000">"</span><span style="color: #000000">,__FILE__,__LINE__,##args);</span><span style="color: #0000ff">return</span><span style="color: #000000">(num);} </span><span style="color: #0000ff">while</span><span style="color: #000000">(</span><span style="color: #000000">0</span><span style="color: #000000">)<br /><br />//lua中调用的c函数定义,实现加法<br /></span><span style="color: #0000ff">int</span><span style="color: #000000"> csum(lua_State</span><span style="color: #000000">*</span><span style="color: #000000"> l)<br />{<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;int</span><span style="color: #000000"> a </span><span style="color: #000000">=</span><span style="color: #000000"> lua_tointeger(l,</span><span style="color: #000000">1</span><span style="color: #000000">) ;<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;int</span><span style="color: #000000"> b </span><span style="color: #000000">=</span><span style="color: #000000"> lua_tointeger(l,</span><span style="color: #000000">2</span><span style="color: #000000">) ;<br />&nbsp;&nbsp;&nbsp;lua_pushinteger(l,a</span><span style="color: #000000">+</span><span style="color: #000000">b) ;<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;return</span><span style="color: #000000"> </span><span style="color: #000000">1</span><span style="color: #000000"> ;<br />}<br /><br /></span><span style="color: #0000ff">int</span><span style="color: #000000"> main(</span><span style="color: #0000ff">int</span><span style="color: #000000"> argc,</span><span style="color: #0000ff">char</span><span style="color: #000000">**</span><span style="color: #000000"> argv)<br />{<br />&nbsp;&nbsp;&nbsp;lua_State </span><span style="color: #000000">*</span><span style="color: #000000"> l </span><span style="color: #000000">=</span><span style="color: #000000"> luaL_newstate() ; //创建lua运行环境<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;if</span><span style="color: #000000"> ( l </span><span style="color: #000000">==</span><span style="color: #000000"> NULL ) err_return(</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">luaL_newstat() failed</span><span style="color: #000000">"</span><span style="color: #000000">);&nbsp;<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;int</span><span style="color: #000000"> ret </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000"> ;<br />&nbsp;&nbsp;&nbsp;ret </span><span style="color: #000000">=</span><span style="color: #000000"> luaL_loadfile(l,</span><span style="color: #000000">"</span><span style="color: #000000">func.lua</span><span style="color: #000000">"</span><span style="color: #000000">) ; //加载lua脚本文件<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;if</span><span style="color: #000000"> ( ret </span><span style="color: #000000">!=</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000"> ) err_return(</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">luaL_loadfile failed</span><span style="color: #000000">"</span><span style="color: #000000">) ;<br />&nbsp;&nbsp;&nbsp;ret </span><span style="color: #000000">=</span><span style="color: #000000"> lua_pcall(l,</span><span style="color: #000000">0</span><span style="color: #000000">,</span><span style="color: #000000">0</span><span style="color: #000000">,</span><span style="color: #000000">0</span><span style="color: #000000">) ;<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;if</span><span style="color: #000000"> ( ret </span><span style="color: #000000">!=</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000"> ) err_return(</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">lua_pcall failed:%s</span><span style="color: #000000">"</span><span style="color: #000000">,lua_tostring(l,</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">)) ;<br /><br />&nbsp;&nbsp;&nbsp;lua_getglobal(l,</span><span style="color: #000000">"</span><span style="color: #000000">width</span><span style="color: #000000">"</span><span style="color: #000000">); //获取lua中定义的变量<br />&nbsp;&nbsp;&nbsp;lua_getglobal(l,</span><span style="color: #000000">"</span><span style="color: #000000">height</span><span style="color: #000000">"</span><span style="color: #000000">);<br />&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000">"</span><span style="color: #000000">height:%ld width:%ld\n</span><span style="color: #000000">"</span><span style="color: #000000">,lua_tointeger(l,</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">),lua_tointeger(l,</span><span style="color: #000000">-</span><span style="color: #000000">2</span><span style="color: #000000">)) ;<br />&nbsp;&nbsp;&nbsp;lua_pop(l,</span><span style="color: #000000">1</span><span style="color: #000000">) ; //恢复lua的栈<br /><br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;int</span><span style="color: #000000"> a </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">11</span><span style="color: #000000"> ;<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;int</span><span style="color: #000000"> b </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">12</span><span style="color: #000000"> ;<br />&nbsp;&nbsp;&nbsp;lua_getglobal(l,</span><span style="color: #000000">"</span><span style="color: #000000">sum</span><span style="color: #000000">"</span><span style="color: #000000">); //调用lua中的函数sum<br />&nbsp;&nbsp;&nbsp;lua_pushinteger(l,a) ;<br />&nbsp;&nbsp;&nbsp;lua_pushinteger(l,b) ;<br />&nbsp;&nbsp;&nbsp;ret </span><span style="color: #000000">=</span><span style="color: #000000"> lua_pcall(l,</span><span style="color: #000000">2</span><span style="color: #000000">,</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">0</span><span style="color: #000000">) ;<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;if</span><span style="color: #000000"> ( ret </span><span style="color: #000000">!=</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000"> ) err_return(</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">lua_pcall failed:%s</span><span style="color: #000000">"</span><span style="color: #000000">,lua_tostring(l,</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">)) ;<br />&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000">"</span><span style="color: #000000">sum:%d + %d = %ld\n</span><span style="color: #000000">"</span><span style="color: #000000">,a,b,lua_tointeger(l,</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">)) ;<br />&nbsp;&nbsp;&nbsp;lua_pop(l,</span><span style="color: #000000">1</span><span style="color: #000000">) ;<br /><br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;const</span><span style="color: #000000"> </span><span style="color: #0000ff">char</span><span style="color: #000000"> str1[] </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">"</span><span style="color: #000000">hello</span><span style="color: #000000">"</span><span style="color: #000000"> ;<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;const</span><span style="color: #000000"> </span><span style="color: #0000ff">char</span><span style="color: #000000"> str2[] </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #000000">"</span><span style="color: #000000">world</span><span style="color: #000000">"</span><span style="color: #000000"> ;<br />&nbsp;&nbsp;&nbsp;lua_getglobal(l,</span><span style="color: #000000">"</span><span style="color: #000000">mystrcat</span><span style="color: #000000">"</span><span style="color: #000000">); //调用lua中的函数mystrcat<br />&nbsp;&nbsp;&nbsp;lua_pushstring(l,str1) ;<br />&nbsp;&nbsp;&nbsp;lua_pushstring(l,str2) ;<br />&nbsp;&nbsp;&nbsp;ret </span><span style="color: #000000">=</span><span style="color: #000000"> lua_pcall(l,</span><span style="color: #000000">2</span><span style="color: #000000">,</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">0</span><span style="color: #000000">) ;<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;if</span><span style="color: #000000"> ( ret </span><span style="color: #000000">!=</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000"> ) err_return(</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">lua_pcall failed:%s</span><span style="color: #000000">"</span><span style="color: #000000">,lua_tostring(l,</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">)) ;<br />&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000">"</span><span style="color: #000000">mystrcat:%s%s = %s\n</span><span style="color: #000000">"</span><span style="color: #000000">,str1,str2,lua_tostring(l,</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">)) ;<br />&nbsp;&nbsp;&nbsp;lua_pop(l,</span><span style="color: #000000">1</span><span style="color: #000000">) ;<br /><br />&nbsp;&nbsp;&nbsp;lua_pushcfunction(l,csum) ; //注册在lua中使用的c函数<br />&nbsp;&nbsp;&nbsp;lua_setglobal(l,</span><span style="color: #000000">"</span><span style="color: #000000">csum</span><span style="color: #000000">"</span><span style="color: #000000">) ; //绑定到lua中的名字csum<br /><br />&nbsp;&nbsp;&nbsp;lua_getglobal(l,</span><span style="color: #000000">"</span><span style="color: #000000">mysum</span><span style="color: #000000">"</span><span style="color: #000000">); //调用lua中的mysum函数，该函数调用本程序中定义的csum函数实现加法<br />&nbsp;&nbsp;&nbsp;lua_pushinteger(l,a) ;<br />&nbsp;&nbsp;&nbsp;lua_pushinteger(l,b) ;<br />&nbsp;&nbsp;&nbsp;ret </span><span style="color: #000000">=</span><span style="color: #000000"> lua_pcall(l,</span><span style="color: #000000">2</span><span style="color: #000000">,</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">0</span><span style="color: #000000">) ;<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;if</span><span style="color: #000000"> ( ret </span><span style="color: #000000">!=</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000"> ) err_return(</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">,</span><span style="color: #000000">"</span><span style="color: #000000">lua_pcall failed:%s</span><span style="color: #000000">"</span><span style="color: #000000">,lua_tostring(l,</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">)) ;<br />&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000">"</span><span style="color: #000000">mysum:%d + %d = %ld\n</span><span style="color: #000000">"</span><span style="color: #000000">,a,b,lua_tointeger(l,</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">)) ;<br />&nbsp;&nbsp;&nbsp;lua_pop(l,</span><span style="color: #000000">1</span><span style="color: #000000">) ;<br /><br />&nbsp;&nbsp;&nbsp;lua_close(l) ; //释放lua运行环境<br /></span><span style="color: #0000ff">&nbsp;&nbsp;&nbsp;return</span><span style="color: #000000"> </span><span style="color: #000000">0</span><span style="color: #000000"> ;<br />}<br /></span></div><img src ="http://www.cppblog.com/xylyan/aggbug/173600.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/xylyan/" target="_blank">意吟</a> 2012-05-03 19:29 <a href="http://www.cppblog.com/xylyan/archive/2012/05/03/173600.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>