??xml version="1.0" encoding="utf-8" standalone="yes"?>久久本道综合久久伊人,亚洲日韩欧美一区久久久久我,亚洲伊人久久精品影院http://www.shnenglu.com/mybios/category/3079.html游戏开?C++ Cocos2d-x OpenGL DirectX 数学 计算机图形学 SQL Server <BR> <BR>zh-cnTue, 19 Jul 2016 07:15:22 GMTTue, 19 Jul 2016 07:15:22 GMT60tolua++导出C++cȝ一些问题和解决Ҏ(gu)http://www.shnenglu.com/mybios/archive/2010/02/09/107616.html李锦?mybios)李锦?mybios)Tue, 09 Feb 2010 11:43:00 GMThttp://www.shnenglu.com/mybios/archive/2010/02/09/107616.htmlhttp://www.shnenglu.com/mybios/comments/107616.htmlhttp://www.shnenglu.com/mybios/archive/2010/02/09/107616.html#Feedback7http://www.shnenglu.com/mybios/comments/commentRss/107616.htmlhttp://www.shnenglu.com/mybios/services/trackbacks/107616.html阅读全文

李锦?mybios) 2010-02-09 19:43 发表评论
]]>
【原创】魔兽争霸III 地图~辑器原理(关键是脚本)http://www.shnenglu.com/mybios/archive/2006/11/19/15404.html李锦?mybios)李锦?mybios)Sat, 18 Nov 2006 16:20:00 GMThttp://www.shnenglu.com/mybios/archive/2006/11/19/15404.htmlhttp://www.shnenglu.com/mybios/comments/15404.htmlhttp://www.shnenglu.com/mybios/archive/2006/11/19/15404.html#Feedback9http://www.shnenglu.com/mybios/comments/commentRss/15404.htmlhttp://www.shnenglu.com/mybios/services/trackbacks/15404.html  注意Q本文纯属是本h从研I兽争霸III地图~辑器的q程中的一U猜惻I所以,不当之处Q还请高手指出。谢谢!

  兽争霸III我以前玩得比较多Q也听说他的地图~辑器非常牛XQ以前也曄想编辑个地图出来。但是,限于当时得水q问题,没有成功。直到最q在研究如何制作游戏的时候,打开兽争霸III的地囄辑器来看Q突然有一U扩然开朗的感觉Q哦Q原来地囄辑器是这样出来的Q闲话不多说Q马上进入正题!

  兽争霸III的地囄辑器使用了一个文件来代表一个地图,地图里包含了什么东西?我无从得知,但是Q从他的~辑器上看,看到~辑器能对地图修改的东西Q就可以大概猜想到有哪些东西。仔l看地图~辑器,看到有那么几个模块:地Ş~辑器、开关编辑器、声音编辑器、物体编辑器、战役编辑器、AI~辑器、物体管理器、输入管理器。我把我的理解逐一说来阅读全文  阅读全文

李锦?mybios) 2006-11-19 00:20 发表评论
]]>
【{贴】Lua ~程技?/title><link>http://www.shnenglu.com/mybios/archive/2006/11/18/15358.html</link><dc:creator>李锦?mybios)</dc:creator><author>李锦?mybios)</author><pubDate>Sat, 18 Nov 2006 07:04:00 GMT</pubDate><guid>http://www.shnenglu.com/mybios/archive/2006/11/18/15358.html</guid><wfw:comment>http://www.shnenglu.com/mybios/comments/15358.html</wfw:comment><comments>http://www.shnenglu.com/mybios/archive/2006/11/18/15358.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/mybios/comments/commentRss/15358.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/mybios/services/trackbacks/15358.html</trackback:ping><description><![CDATA[ <div id="5rflb5j" class="page"> <a >Lua</a> ?5.1 版本已经正式发布。现在,我们应该把全部讨论放在这个版本上?br /><br /><img title="Hot!" height="11" alt="Hot!" hspace="4" src="http://blog.codingnow.com/cloud//images/idea.gif" width="7" border="0" /><strong>应该量使用 local 变量而非 global 变量</strong>。这?<a >Lua</a> 初学者最Ҏ(gu)犯的错误。global 变量实际上是攑֜一张全局?table 里的。global 变量实际上是利用一?string (变量名作 key) 去访问这?table 。虽?a target="_blank"><img title="在新H口中打开" height="11" alt="[InterWiki]" hspace="4" src="http://blog.codingnow.com/cloud//images/inter.gif" width="11" border="0" /></a><a >Lua5 ?table 效率很高</a> Q但是相对于 local 变量Q依然有很大的效率损失。local 变量是直接通过 <a >Lua</a> 的堆栈访问的。有?global 变量的访问是不经意的Q比如我们有双重循环操作一个P代的 tableQ?br /><pre class="code"><span id="f3x1rn5" class="kw1">for</span> k1,v1 <span id="5zzj5bv" class="kw1">in</span><span id="fv5rr35" class="kw1">pairs</span><span id="h3x5v3f" class="br0">(</span>tbl<span id="hnd5f1x" class="br0">)</span><span id="5n5jvx5" class="kw1">do</span><span id="5d33vh1" class="kw1">for</span> k2,v2 <span id="jvjp35j" class="kw1">in</span><span id="vxlpl55" class="kw1">pairs</span><span id="ldpj55t" class="br0">(</span>v1<span id="vhr3p5x" class="br0">)</span><span id="jvxb5rr" class="kw1">do</span> ... <span id="ld5jn3l" class="kw1">end</span> end</pre><br /><br />q里Qpairs 其实是一个全局变量应用的函数。如果我们这样做Q?br /><pre class="code"><span id="rb355p5" class="kw1">do</span><span id="n5d533r" class="kw1">local</span><span id="5vlfv5z" class="kw1">pairs</span>=pairs <span id="np5ppr5" class="kw1">for</span> k1,v1 <span id="ztfzxzj" class="kw1">in</span><span id="5xf3d5r" class="kw1">pairs</span><span id="f55rtv5" class="br0">(</span>tbl<span id="ztx5xhb" class="br0">)</span><span id="nzl351d" class="kw1">do</span><span id="nrt5tjb" class="kw1">for</span> k2,v2 <span id="5fhp5l5" class="kw1">in</span><span id="tv3bn3x" class="kw1">pairs</span><span id="d5zxdf3" class="br0">(</span>v1<span id="nh5n515" class="br0">)</span><span id="5pj555x" class="kw1">do</span> ... <span id="5d3r5jt" class="kw1">end</span><span id="pzdjnlt" class="kw1">end</span> end</pre><br /><br />效率会稍微提高一些。如果是单层循环Q这样做没有意义。因?for ... in 循环中的 pairs q个函数只会被调用一ơ,而不是每ơ@环都去调。我们的原则其实是,被多ơ读取的 global 变量Q都应该提取出来攑ֈ local 变量中?br /><br /><img title="Hot!" height="11" alt="Hot!" hspace="4" src="http://blog.codingnow.com/cloud//images/idea.gif" width="7" border="0" /><strong>警惕临时变量</strong> 字符串的q接操作Q会产生新的对象。这是由 lua 本n?string 理机制D的。lua ?VM 内对相同?string 永远只保留一份唯一 copy Q这P所有字W串比较?yu)可以简化ؓ地址比较。这也是 lua ?table 工作很快的原因之一。这U?string 理的策略,?java {一P所以跟 java 一P应该量避免在@环内不断的连接字W串Q比?a = a..x q样。每ơ运行,都很可能会生成一份新?copy ?br /><br />同样Q记住,每次构造一?table 都会多一?table ?copy 。比如在 lua 里,把^面坐标封装成 { x, y } 用于参数传递,需要考虑q个问题。每ơ你x造一个坐标对象传递给一个函敎ͼ{ 10,20 }  q样明确的写出,都会构造一个新?table 出来。要么,我们惛_法考虑 table 的重用;要么Q干脆用 x,y 两个参数传递坐标?br /><br />同样需要注意的是以 function foo (...) q种方式定义函数Q?... q种不定参数Q每ơ调用的时候都会被定义Z?table 存放不定数量的参数?br /><br />q些临时构造的对象往往要到 gc 的时候才被回Ӟq于频繁?gc 有时候正是效率瓶颈?br /><br /><img title="Hot!" height="11" alt="Hot!" hspace="4" src="http://blog.codingnow.com/cloud//images/idea.gif" width="7" border="0" /><strong>使用 closure 代替 table</strong> 上面提到装坐标的问题。诚Ӟ我们可以?{ x=1,y=2 } q样装一个坐标。不q还有一个方法可供选择。它E微轻量一炏V?br /><br /><pre class="code"><span id="rd3r5r5" class="kw1">function</span> point <span id="5jv3tbb" class="br0">(</span>x,y<span id="fzl15dv" class="br0">)</span><span id="33555b1" class="kw1">return</span><span id="hl35ttb" class="kw1">function</span><span id="5ztztrj" class="br0">(</span><span id="53l5b5t" class="br0">)</span><span id="5v5ztrh" class="kw1">return</span> x,y <span id="xzbp3rt" class="kw1">end</span> end   <span id="lvzb5tr" class="co1">-- 使用范例</span> p=point<span id="lfh35jf" class="br0">(</span><span id="5ptfd5p" class="nu0">1</span>,<span id="5h5jftj" class="nu0">2</span><span id="zzv555x" class="br0">)</span><span id="jvh5x5r" class="kw1">print</span><span id="551d55r" class="br0">(</span>p<span id="xzl5px3" class="br0">(</span><span id="53vdf5n" class="br0">)</span><span id="33prd55" class="br0">)</span><span id="tvpfxnn" class="co1">-- 输出 1 2 </span>  </pre><br /><br />如果你愿意,q可以做的复杂一点:<br /><pre class="code"><span id="r3f5xfn" class="kw1">function</span> point <span id="bv3b3zp" class="br0">(</span>x,y<span id="3xr15lt" class="br0">)</span><span id="tv33t5d" class="kw1">return</span><span id="btfdvdb" class="kw1">function</span><span id="r5nhj3l" class="br0">(</span>idx<span id="tvh5jx5" class="br0">)</span><span id="bd5bvl3" class="kw1">if</span> idx==<span id="l3f5x5h" class="st0">"x"</span><span id="xzbjtrp" class="kw1">then</span><span id="3hrpdtj" class="kw1">return</span> x <span id="hblxr3l" class="kw1">elseif</span> idx==<span id="btfj3rx" class="st0">"y"</span><span id="vp5v3d5" class="kw1">then</span><span id="bdfrtrr" class="kw1">return</span> y <span id="3bl3335" class="kw1">else</span><span id="5htf35x" class="kw1">return</span> x,y <span id="33nr5vn" class="kw1">end</span><span id="lnhtfv3" class="kw1">end</span> end   <span id="5f55hxn" class="co1">-- 使用范例</span> p=point<span id="dfrln35" class="br0">(</span><span id="53r55xd" class="nu0">1</span>,<span id="3rlxh3b" class="nu0">2</span><span id="53j5f5v" class="br0">)</span><span id="1lvzbjz" class="kw1">print</span><span id="r3ft15d" class="br0">(</span>p<span id="fdh3vbr" class="br0">(</span><span id="zfjlfnb" class="st0">"x"</span><span id="53d555b" class="br0">)</span><span id="tv3b5zr" class="br0">)</span><span id="5h5n5zn" class="co1">-- 1</span><span id="rx5lrzx" class="kw1">print</span><span id="535vrhn" class="br0">(</span>p<span id="p5zxbhn" class="br0">(</span><span id="5prvx33" class="st0">"y"</span><span id="1lprlb3" class="br0">)</span><span id="n3n35l5" class="br0">)</span><span id="lnhjft3" class="co1">-- 2 </span>  </pre><br /><br />x,y 实际被存攑֜ closure 里,每次调用 function point 都有一份独立的 closure。当Ӟfunction ?code 只有一份?br /><br /><img title="Hot!" height="11" alt="Hot!" hspace="4" src="http://blog.codingnow.com/cloud//images/idea.gif" width="7" border="0" /><strong>设法减少?C ?Lua 传递字W串</strong> 字符串常量在 Lua VM 内部工作的非常快Q但是一个从 C ?lua vm 通过 lua_pushstring 之类?api 传递进 VM Ӟ需要掂量一下了。这臛_包含一个再 hash 和匹配的q程?a target="_blank"><img title="在新H口中打开" height="11" alt="[InterWiki]" hspace="4" src="http://blog.codingnow.com/cloud//images/inter.gif" width="11" border="0" /></a><a >我的 Blog 上的一文章讨Zq个问题</a>?br /><br /><img title="Hot!" height="11" alt="Hot!" hspace="4" src="http://blog.codingnow.com/cloud//images/idea.gif" width="7" border="0" /><strong>lua 中的l承</strong> lua 中实?OO Q虚表往往讄一?metatable q设|?__index Q而承则?metatable ?__index 把虚表串h。当cȝ承层ơ过多的时候,效率比较低,那么可以用下面q个技巧?br /><pre class="code"><span id="335n5v3" class="kw1">function</span> inherit<span id="1pr3555" class="br0">(</span>sub,super<span id="vpjnfv3" class="br0">)</span><span id="tnrd3l3" class="kw1">setmetatable</span><span id="5rdn35n" class="br0">(</span>sub, <span id="l3fvn1z" class="br0">{</span> __index=<span id="33xrvlb" class="kw1">function</span><span id="5hdfp35" class="br0">(</span>t,k<span id="53x5hzf" class="br0">)</span><span id="5z5n3zp" class="kw1">local</span> ret=super<span id="zl335t5" class="br0">[</span>k<span id="hbn3zhn" class="br0">]</span> sub<span id="xr3p1bb" class="br0">[</span>k<span id="5jdpbpf" class="br0">]</span>=ret <span id="f3z5l5n" class="kw1">return</span> ret <span id="535lz5t" class="kw1">end</span><span id="pbvrb3f" class="br0">}</span><span id="53j3hp3" class="br0">)</span><span id="jjd135x" class="kw1">end</span></pre><br /><br /><img title="Hot!" height="11" alt="Hot!" hspace="4" src="http://blog.codingnow.com/cloud//images/idea.gif" width="7" border="0" /><strong>利用逻辑q算的短路效?/strong> lua ~程中,and or ?C 一h有短路效应的Q不q他们的q回值ƈ?bool cdQ而是表达式中的左值或者右倹{我们常常利用这个特性来化代码?br /><pre class="code"><span id="lvh55zt" class="kw1">function</span> foo<span id="53xnpv5" class="br0">(</span>arg<span id="rjhdnn3" class="br0">)</span> arg=arg <span id="z3j5rz3" class="kw1">or</span><span id="vdhtv33" class="st0">"default"</span> ... <span id="3ztvpfh" class="kw1">end</span></pre><br />利用 or q算赋缺省值是最常用的技巧。上例中Q如?arg ?nil Qarg ׃被赋gؓ "default" 。但是这个技巧有个缺P当缺省值是 true 的时候会有点问题?br /><pre class="code">a=a <span id="5x5lzhf" class="kw1">or</span><span id="5hlv5vn" class="kw1">true</span><span id="1txrt3v" class="co1">-- 错误的写法,?a 明确写ؓ false 的时候,也会被改变成 true ?/span> a= a ~= <span id="nz3pvt3" class="kw1">false</span><span id="jtxz1t3" class="co1">-- 正确的写法,?a ?nil 的时候,被赋gؓ true Q?false 则不变?</span>  </pre><br /><br />另外Qy妙?and or q可以实现类?C 语言中的 ?: 三元操作Q?br /><pre class="code"><span id="f35hj5n" class="kw1">function</span><span id="xjtf3h3" class="kw1">max</span><span id="pbv3555" class="br0">(</span>a,b<span id="5dpzdjb" class="br0">)</span><span id="rt3zb55" class="kw1">return</span> a>b <span id="33nbxl5" class="kw1">and</span> a <span id="fjt5zzx" class="kw1">or</span> b <span id="d5h5fv3" class="kw1">end</span></pre><br />上面q个函数可以q回 a ?b 中较大的一个,光辑cM C 语言中的 return (a>b) ? a : b ;</div> <img src ="http://www.shnenglu.com/mybios/aggbug/15358.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/mybios/" target="_blank">李锦?mybios)</a> 2006-11-18 15:04 <a href="http://www.shnenglu.com/mybios/archive/2006/11/18/15358.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【{贴】通过例子学习Luahttp://www.shnenglu.com/mybios/archive/2006/11/18/15356.html李锦?mybios)李锦?mybios)Sat, 18 Nov 2006 06:34:00 GMThttp://www.shnenglu.com/mybios/archive/2006/11/18/15356.htmlhttp://www.shnenglu.com/mybios/comments/15356.htmlhttp://www.shnenglu.com/mybios/archive/2006/11/18/15356.html#Feedback0http://www.shnenglu.com/mybios/comments/commentRss/15356.htmlhttp://www.shnenglu.com/mybios/services/trackbacks/15356.html 一.Hello World

1.前言
  
  偶最q在学习Lua, 所以写出心得和大家׃n, 争取一天写一? 嘿嘿.
  才开始学所以内容很? 希望大家包涵.
  Lua是一U完全免费的脚本语言, 可以和C/C++语言紧密l合,
  它的官方|站在http://www.lua.org. 在网站上可以下蝲到l(f)ua的源? 没有?br />  执行版本, 不过不用担心, 因ؓlua源码可以在Q何一UC/C++的编译器上编?
  
  如果要学习Lua, 官方|站上的Reference是必备的Q上面有每个命o的用法,非常详细?br />  参考手?http://www.lua.org/manual/5.0/
  作者写的Programming in Lua http://www.lua.org/pil/
  
2.~译
  如果用的VC6, 可以下蝲所需的project文g,地址?br />  http://sourceforge.net/project/showfiles.php?group_id=32250&package_id=115604
  VSNET2003可以下蝲q个sln文ghttp://home.comcast.net/~vertigrated/lua/vs7.zip
  偶用的是cygwin和linux, 打入以下命o卛_,
  tar -zxvf lua-5.0.2.tar.gz
  cd lua-5.0.2
  sh ./configure
  make
  q样O(jin)K了?br />  Z以后使用方便Q最好把bin目录加入到path里面?br />  
3."Hello, world!"
  现在开始偶们的W一个小E序"Hello, world!"
  把以下程序打入文件e01.lua
  
  ?:e01.lua
  -- Hello World in Lua
  print("Hello World.")
  
  Lua有两U执行方式,一U是嵌入到CE序中执行,q有一U是直接从命令行方式下执行?br />  q里Z调试方便Q采用第二种方式Q执行命?lua e01.lua
  
  输出l果应该是:
  Hello World.
  
4.E序说明
  W一?-- Hello World in Lua
  q句是注释,其中--和C++中的//意思是一L
  W二?print("Hello World.")
  调用lua内部命oprintQ输?Hello World."字符串到屏幕QLua中的字符串全部是?括v来的?br />  q个命o是一个函数的调用Qprint是lua的一个函敎ͼ?Hello World."是print的参数?br />  
5.试试?/b>
  在Lua中有不少字符串的处理操作Q本ơ的译֐试试看的内容是Q找接两个字W串的操作,
  q且print出来?

?程控制

1. 函数的?br />  以下E序演示了如何在Lua中用函? 及局部变?br />  例e02.lua
  -- functions
  function pythagorean(a, b)
  local c2 = a^2 + b^2
  return sqrt(c2)
  end
  print(pythagorean(3,4))
  
  q行l果
  5
  
  E序说明
  在Lua中函数的定义格式?
  function 函数?参数)
  ...
  end
  与Pascal语言不同, end不需要与begin配对, 只需要在函数l束后打个end可以了.
  本例函数的作用是已知直角三角形直角边, 求斜辚w? 参数a,b分别表示直角辚w,
  在函数内定义了local形变量用于存储斜边的qx. 与C语言相同, 定义在函数内的代
  码不会被直接执行, 只有ȝ序调用时才会被执?
  local表示定义一个局部变? 如果不加local刚表Cc2Z个全局变量, local的作用域
  是在最里层的end和其配对的关键字之间, 如if ... end, while ... end{。全局变量?br />  作用域是整个E序?br />  
  2. 循环语句
  例e03.lua
  -- Loops
  for i=1,5 do
  print("i is now " .. i)
  end
  
  q行l果
  i is now 1
  i is now 2
  i is now 3
  i is now 4
  i is now 5
  
  E序说明
  q里偶们用到了for语句
  for 变量 = 参数1, 参数2, 参数3 do
  循环?br />  end
  变量以参数3为步? 由参?变化到参?
  例如:
  for i=1,f(x) do print(i) end
  for i=10,1,-1 do print(i) end
  
  q里print("i is now " .. i)中,偶们用到?.Q这是用来连接两个字W串的,
  偶在(1)的试试看中提到的Q不知道你们{对了没有?br />  虽然q里i是一个整型量QLua在处理的时候会自动转成字符串型Q不需偶们费心?br />  
  3. 条g分支语句
  例e04.lua
  -- Loops and conditionals
  for i=1,5 do
  print(“i is now ?.. i)
     if i < 2 then
     print(“small?
     elseif i < 4 then
     print(“medium?
     else
     print(“big?
     end
  end
  
  q行l果
  i is now 1
  small
  i is now 2
  medium
  i is now 3
  medium
  i is now 4
  big
  i is now 5
  big
  
  E序说明
  if else用法比较? cM于C语言, 不过此处需要注意的是整个if只需要一个end,
  哪怕用了多个elseif, 也是一个end.
  例如
    if op == "+" then
     r = a + b
    elseif op == "-" then
     r = a - b
    elseif op == "*" then
     r = a*b
    elseif op == "/" then
     r = a/b
    else
     error("invalid operation")
    end
  
  
  4.试试?/b>
  Lua中除了for循环以外, q支持多U@? Lwhile...do和repeat...until改写本文中的forE序

?Lua数据l构

 1.?/b>
  Lua语言只有一U基本数据结? 那就是table, 所有其他数据结构如数组?
  cd, 都可以由table实现.
  例e05.lua
  -- Arrays
  myData = {}
  myData[0] = “foo?br />  myData[1] = 42
  
  -- Hash tables
  myData[“bar”] = “baz?br />  
  -- Iterate through the
  -- structure
  for key, value in myData do
  print(key .. ??.. value)
  end
  
  输出l果
  0=foo
  1=42
  bar=baz
  
  E序说明
  首先定义了一个table myData={}, 然后用数字作Z标赋了两个值给? q种
  定义Ҏ(gu)cM于C中的数组, 但与数组不同的是, 每个数组元素不需要ؓ相同cd,
  像本例中一个ؓ整型, 一个ؓ字符?
  
  E序W二部分, 以字W串做ؓ下标, 又向table内增加了一个元? q种table非常
  像STL里面的map. table下标可以为Lua所支持的Q意基本类? 除了nilg?
  
  Lua对Table占用内存的处理是自动? 如下面这D代?br />    a = {}
    a["x"] = 10
    b = a   -- `b' refers to the same table as `a'
    print(b["x"]) --> 10
    b["x"] = 20
    print(a["x"]) --> 20
    a = nil  -- now only `b' still refers to the table
    b = nil  -- now there are no references left to the table
  b和a都指向相同的table, 只占用一块内? 当执行到a = nil? b仍然指向table,
  而当执行到b=nil? 因ؓ没有指向table的变量了, 所以Lua会自动释放table所占内?br />  
  3.Table的嵌?/b>
  Table的用还可以嵌套Q如下例
  例e06.lua
  -- Table ‘constructor?br />  myPolygon = {
  color=“blue?
  thickness=2,
  npoints=4;
  {x=0,  y=0},
  {x=-10, y=0},
  {x=-5, y=4},
  {x=0,  y=4}
  }
  
  -- Print the color
  print(myPolygon[“color”])
  
  -- Print it again using dot
  -- notation
  print(myPolygon.color)
  
  -- The points are accessible
  -- in myPolygon[1] to myPolygon[4]
  
  -- Print the second point’s x
  -- coordinate
  print(myPolygon[2].x)
  
  E序说明
  首先建立一个table, 与上一例不同的是,在table的constructor里面有{x=0,y=0},
  q是什么意思呢Q?q其实就是一个小table, 定义在了大table之内, table?br />  table名省略了.
  最后一行myPolygon[2].xQ就是大table里面table的访问方?
  
?函数的调?/font>

 1.不定参数
  例e07.lua
  -- Functions can take a
  -- variable number of
  -- arguments.
  function funky_print (...)
  for i=1, arg.n do
  print("FuNkY: " .. arg[i])
  end
  end
  
  funky_print("one", "two")
  
  q行l果
  FuNkY: one
  FuNkY: two
  
  E序说明
  * 如果?..为参? 则表C参数的数量不定.
  * 参数会自动存储C个叫arg的table?
  * arg.n中存攑֏数的个数. arg[]加下标就可以遍历所有的参数.
  
  
  2.以table做ؓ参数
  例e08.lua
  -- Functions with table
  -- parameters
  function print_contents(t)
  for k,v in t do
  print(k .. "=" .. v)
  end
  end
  print_contents{x=10, y=20}
  
  q行l果
  x=10
  y=20
  
  E序说明
  * print_contents{x=10, y=20}q句参数没加圆括? 因ؓ以单个table为参数的时? 不需要加圆括?br />  * for k,v in t do q个语句是对table中的所有值遍? k中存攑֐U? v中存攑ր?br />  
  
  3.把Lua变成cMXML的数据描q语a
  例e09.lua
  function contact(t)
  -- add the contact ‘t? which is
  -- stored as a table, to a database
  end
  
  contact {
  name = "Game Developer",
  email = "hack@ogdev.net",
  url = "http://www.ogdev.net",
  quote = [[
  There are
  10 types of people
  who can understand binary.]]
  }
  
  contact {
  -- some other contact
  }
  
  E序说明
  * 把function和tablel合, 可以使Lua成ؓ一U类似XML的数据描q语a
  * e09中contact{...}, 是一U函数的调用Ҏ(gu), 不要弄؜?br />  * [[...]]是表C多行字W串的方?br />  * 当用C API时此U方式的优势更明? 其中contact{..}部分可以另外存成一配置文g
  
  4.试试?/b>
  x看哪些地方可以用Ce09中提到的配置Ҏ(gu)呢?
  

?Lua与C的交?/strong>

 1.?/b>
  
  Lua与C/C++l合是很紧密? Lua与C++交互是徏立在Lua与C的基上的, 所
  以偶先从Lua与C讲v.
  
  正如W一讲所? q行LuaE序或者说调用Lua主要有两U方?
  * 通过命o行执?Lua"命o
  * 通过Lua的C?br />  虽然此前偶们一直用W一U方? 但偶要告诉你, 通过Lua的C库执行才是游戏中
  常用的方?
  
  2.Lua的C?/b>
  
  Lua的C库可以做为Shared Library调用, 但一般开发游戏时会把Lua的所有源E序
  都包含在? q不把Lua~译成共享库的Ş? 因ؓLuaE序只有100多K, 而且几乎
  可以在Q何编译器下Clean Compile. 带Lua源程序的另一个好处时, 可以随时对Lua
  本nq行扩充, 增加偶们所需的功?
  
  Lua的C库提供一pdAPI:
  * 理全局变量
  * 理tables
  * 调用函数
  * 定义新函? q也可以完全由C实现
  * 垃圾攉器Garbage collector, 虽然Lua可以自动q行, 但往往不是立即执行?
   所以对实时性要求比较高的程? 会自p用垃圾收集器
  * 载入q执行LuaE序, q也可以由Lua自n实现
  * MLua可以实现的功? 都可以通过Lua的C API实现, q对于优化程序的q行速度
   有帮? l常调用的共用的LuaE序片断可以转成CE序, 以提高效? qLua都是C写的
   q有什么C不能实现?
  
  3.Lua与C集成的例?/b>
  例e10.c
  /* A simple Lua interpreter. */
  #include
  #include
  int main(int argc, char *argv[]) {
  char line[BUFSIZ];
  lua_State *L = lua_open(0);
  while (fgets(line, sizeof(line), stdin) != 0)
  lua_dostring(L, line);
  lua_close(L);
  return 0;
  }
  
  ~译
  Linux/Cygwin
  * 先编译Lua, q把头文件放入include路径
  * gcc e10.c -llua -llualib -o e10
  
  VC6/VC2003
  * 先编译Lua, 在Option中设|头文g和库文g路径
  * 新徏工程,在工E配|中加入附加库lua.lib和lualib.lib
  * ~译成exe
  
  q行l果
  本程序的功能是实C个Lua解释? 输入的每行字W都会被解释成Luaq执?
  
  E序说明
  * #include 包含lua头文? 然后才可以用API
  * lua_State *L = lua_open(0) 打开一个Lua执行?br />  * fgets(line, sizeof(line), stdin) 从标准输入里d一?br />  * lua_dostring(L, line) 执行此行
  * lua_close(L) 关闭Lua执行?br />  
  
  例e11.c
  /* Another simple Lua interpreter. */
  #include
  #include
  #include
  int main(int argc, char *argv[]) {
  char line[BUFSIZ];
  lua_State *L = lua_open(0);
  lua_baselibopen(L);
  lua_iolibopen(L);
  lua_strlibopen(L);
  lua_mathlibopen(L);
  while (fgets(line, sizeof(line), stdin) != 0)
  lua_dostring(L, line);
  lua_close(L);
  return 0;
  }
  
  q行l果
  本程序的功能是实C个Lua解释? 输入的每行字W都会被解释成Luaq执?
  与上例不同的? 本例调用了Lua的一些标准库.
  
  E序说明
  * #include 包含Lua的标准库
  * 以下q几行是用来dLua的一些库, q样偶们的LuaE序可以有更多的功?
  lua_baselibopen(L);
  lua_iolibopen(L);
  lua_strlibopen(L);
  lua_mathlibopen(L);
  
  4.试试?/b>
  把上面两个小例子在你熟?zhn)的编译器中编译执? q试试能否与Lua源码树一L?br />
?C/C++中用Lua函数

1.?br />  偶们q次主要说说怎么由Lua定义函数, 然后在C或者C++中调? q里偶们
  暂不涉及C++的对象问? 只讨用函数的参数, q回值和全局变量的?

  2.E序
  q里偶们在e12.lua里先定义一个简单的add(), x,y为加法的两个参数,
  return 直接q回相加后的l果.
  
  例e12.lua
  -- add two numbers
  function add ( x, y )
  return x + y
  end
  
  在前一ơ里, 偶们说到 lua_dofile() 可以直接在C中执行lua文g. 因ؓ偶们
  q个E序里只定义了一个add()函数, 所以程序执行后q不直接l果, 效果相当
  于在C中定义了一个函C?
  
  Lua的函数可以有多个参数, 也可以有多个q回? q都是由?stack)实现?
  需要调用一个函数时, 把q个函数压入? 然后序压入所有参? 然后?br />  lua_call()调用q个函数. 函数q回? q回g是存攑֜栈中. q个q程?br />  汇编执行函数调用的过E是一L.
  
  例e13.cpp 是一个调用上面的Lua函数的例?br />  #include
  
  extern "C" { // q是个C++E序, 所以要extern "C",
     // 因ؓlua的头文g都是C格式?br />  #include "lua.h"
  #include "lualib.h"
  #include "lauxlib.h"
  }
  
  /* the Lua interpreter */
  lua_State* L;
  
  int luaadd ( int x, int y )
  {
  int sum;
  
  /* the function name */
  lua_getglobal(L, "add");
  
  /* the first argument */
  lua_pushnumber(L, x);
  
  /* the second argument */
  lua_pushnumber(L, y);
  
  /* call the function with 2
    arguments, return 1 result */
  lua_call(L, 2, 1);
  
  /* get the result */
  sum = (int)lua_tonumber(L, -1);
  lua_pop(L, 1);
  
  return sum;
  }
  
  int main ( int argc, char *argv[] )
  {
  int sum;
  
  /* initialize Lua */
  L = lua_open();
  
  /* load Lua base libraries */
  lua_baselibopen(L);
  
  /* load the script */
  lua_dofile(L, "e12.lua");
  
  /* call the add function */
  sum = luaadd( 10, 15 );
  
  /* print the result */
  printf( "The sum is %d\n", sum );
  
  /* cleanup Lua */
  lua_close(L);
  
  return 0;
  }
  
  E序说明:
  main中过E偶们上ơ已l说q了, 所以这ơ只说说luaadd的过E?br />  * 首先用lua_getglobal()把add函数压栈
  * 然后用lua_pushnumber()依次把x,y压栈
  * 然后调用lua_call(), q且告诉E序偶们有两个参C个返回?br />  * 接着偶们从栈取回返回? 用lua_tonumber()
  * 最后偶们用lua_pop()把返回值清?br />  
  q行l果:
  The sum is 25
  
  ~译Ҏ(gu)
  Linux下把E序存成e13.cpp
  g++ e13.cpp -llua -llualib -o e13
  ./e13
  
  VC下编译方?br />  * 首先建立一个空的Win32 Console Application Project
  * 把e13.cpp加入工程?br />  * 点project setting,然后讄link选项, 再加上lua.lib lualib.lib两个额外的库
  * 最后编?br />  
  建立好的project可以在这里下?br />  VC http://tonyandpaige.com/tutorials/luaadd.zip
  Linux http://tonyandpaige.com/tutorials/luaadd.tar.gz
  
  3.全局变量
  上面偶们用到了lua_getglobal()但ƈ没有详细? q里偶们再D两个例子来说下全局变量
  lua_getglobal()的作用就是把lua中全局变量的值压入栈
  lua_getglobal(L, "z");
  z = (int)lua_tonumber(L, 1);
  lua_pop(L, 1);
  假设LuaE序中定义了一个全局变量z, q段程序就是把z的值取出放入C的变量z?
  
  另外Lua中还有一个对应的函数l(f)ua_setglobal(), 作用是用栈顶的值填充指定的全局变量
  lua_pushnumber(L, 10);
  lua_setglobal(L, "z");
  例如q段程序就是把lua中的全局变量z设ؓ10, 如果lua中未定义z的话, ׃自动创徏一?br />  全局变量zq设?0.
  
  4.试试?/b>
  自己写个函数用C/C++来调用下试试

?调用C/C++函数

1.前言
  上次偶说CC/C++中调用Lua的函? 然后有朋友问从Lua中如何调用C/C++?br />  函数, 所以偶们这ơ就来说说这个问? 首先偶们会在C++中徏立一个函? 然后
  告知Lua有这个函? 最后再执行? 另外, ׃函数不是在Lua中定义的, 所?br />  无法定函数的正? 可能在调用过E中会出? 因此偶们q会说说Lua出错?br />  理的问题.
  
  2.Lua中调用C函数
  在lua中是以函数指针的形式调用函数, q且所有的函数指针都必L_下此U?br />  cd:
  typedef int (*lua_CFunction) (lua_State *L);
  
  也就是说, 偶们在C++中定义函数时必须以lua_State为参? 以int回值才?br />  被Lua所调用. 但是不要忘记? 偶们的lua_State是支持栈? 所以通过栈可?br />  传递无I个参数, 大小只受内存大小限制. 而返回的intg只是指返回值的个数
  真正的返回值都存储在lua_State的栈? 偶们通常的做法是做一个wrapper, ?br />  所有需要调用的函数都wrap一? q样可以调用Q意的函数?
  
  下面q个例子是一个C++的average()函数, 它将展示如何用多个参数ƈq回多个?br />  
  例e14.cpp
  #include
  
  extern "C" {
  #include "lua.h"
  #include "lualib.h"
  #include "lauxlib.h"
  }
  
  /* the Lua interpreter */
  lua_State* L;
  
  static int average(lua_State *L)
  {
  /* get number of arguments */
  int n = lua_gettop(L);
  double sum = 0;
  int i;
  
  /* loop through each argument */
  for (i = 1; i <= n; i++)
  {
  /* total the arguments */
  sum += lua_tonumber(L, i);
  }
  
  /* push the average */
  lua_pushnumber(L, sum / n);
  
  /* push the sum */
  lua_pushnumber(L, sum);
  
  /* return the number of results */
  return 2;
  }
  
  int main ( int argc, char *argv[] )
  {
  /* initialize Lua */
  L = lua_open();
  
  /* load Lua base libraries */
  lua_baselibopen(L);
  
  /* register our function */
  lua_register(L, "average", average);
  
  /* run the script */
  lua_dofile(L, "e15.lua");
  
  /* cleanup Lua */
  lua_close(L);
  
  return 0;
  }
  
  例e15.lua
  -- call a C++ function
  
  avg, sum = average(10, 20, 30, 40, 50)
  
  print("The average is ", avg)
  print("The sum is ", sum)
  
  
  E序说明:
  * lua_gettop()的作用是q回栈顶元素的序? ׃Lua的栈是从1开始编L,
   所以栈元素的序号也相当于栈中的元素个? 在这? 栈中元素的个数就
   是传入的参数个数.
  * for循环计算所有传入参数的d. q里用到了数D{换lua_tonumber().
  * 然后偶们用lua_pushnumber()把^均值和dpush到栈?
  * 最? 偶们q回2, 表示有两个返回?
  * 偶们虽然在C++中定义了average()函数, 但偶们的LuaE序q不知道, 所以需
   要在main函数中加?br />  
    /* register our function */
  lua_register(L, "average", average);
  
   q两行的作用是告诉e15.lua有average()q样一个函?
  * q个E序可以存成cpp也可以存成c, 如果?c为扩展名׃需要加extern "C"
  
  ~译的方法偶们上ơ说q了, Ҏ(gu)相同.
  e15.lua执行的方法只能用上例中的C++中执? 而不能用命o行方式执?
  
  3.错误处理
  在上例中, 偶们没有对传入的参数是否为数字进行检? q样做不? 所以这里偶
  们再加上错误处理的片?
  
  把这D加在for循环之内:
  if (!lua_isnumber(L, i)) {
  lua_pushstring(L, "Incorrect argument to 'average'");
  lua_error(L);
  }
  q段的作用就是检传入的是否为数?
  
  加上q段之后, 偶们debug的时候就会简单许? 对于l合两种语言的编E? 它们?br />  间传递数据的正确性检是非常重要?
  
  q里有别人写好的例子:
  VC?http://tonyandpaige.com/tutorials/luaavg.zip
  Linux?http://tonyandpaige.com/tutorials/luaavg.tar.gz
  


李锦?mybios) 2006-11-18 14:34 发表评论
]]>
【{贴】如何在C++中集成LUA脚本(LuaWrapper For C++?http://www.shnenglu.com/mybios/archive/2006/11/18/15339.html李锦?mybios)李锦?mybios)Sat, 18 Nov 2006 02:00:00 GMThttp://www.shnenglu.com/mybios/archive/2006/11/18/15339.htmlhttp://www.shnenglu.com/mybios/comments/15339.htmlhttp://www.shnenglu.com/mybios/archive/2006/11/18/15339.html#Feedback5http://www.shnenglu.com/mybios/comments/commentRss/15339.htmlhttp://www.shnenglu.com/mybios/services/trackbacks/15339.html作者: 沐枫 Q第二h生成员)
版权所有{载请注明原出?br />主页Q第二h?http://www.d2-life.com
   http://www.d2-life.com/LBS/blogview.asp?logID=41

Z么要用Lua作脚本?
  使用Lua作脚本,主要是因为它?yu)y玲珑Q体U小Q运行快Q,而且它的语法又比较简单明了。不q,使用LuaAPILua引擎集成到程序中Q确实有一些不方便——用落木随风|友的话来说Q就?p用汇~?。当Ӟ现在你不用再q么辛苦了,因ؓ你可以用LuaWrapper For C++。用这个工P在C++中集成Lua脚本是轻而易丄事。你原有的C++函数和类Q几乎不需要Q何改变,可以与Lua脚本׃n?br />  我们接下来,用实例来说明Q如何用LuaWrapper来集成Lua脚本C的程序中厅R?br />
1.  创徏Lua引擎
  LuaWrap lua; 或?LuaWrap* lua = new LuaWrap;
  创徏一个LuaWrap对象Q就是创Z个Lua脚本引擎。ƈ且根据Lua的特性,你可以创ZQ意多个Lua引擎Q甚臛_以分布在不同的线E当中?br />
2.  装蝲q执行脚本程?br />  你可以从~冲Z装蝲Lua脚本Q?br />  lua.LoadString(
    "print('Hello World')"
  );
  当然Q你也可以从文g中装入,q执行Lua脚本Q?br />  Lua.LoadFile("./test.lua");
  Lua的脚本,可以是源代码Q也可以l过~译后的中间代码。也怽对编译后的中间代码更感兴——如果你不希望让源代码赤裸裸的袒露在大家的眼前?br />
3.  获取和设|Lua变量
  能够获取和设|脚本变量的内容Q是一个最基本的功能。你可以使用GetGlobal和SetGlobal函数来做到这一点:
  (1)  获取变量Q?br />    int a = lua.GetGlobal<int>("a");
    LuaTable table = lua.GetGlobal<LuaTable>("t");
    q里Q?lt;> 里头的类型,是惌的变量的cd?br />  (2)  讄变量Q?br />    lua.SetGlobal("a", a);
    lua.SetGlobal("t", table);

4.  调用Lua函数
  使用Call函数Q就可以很简单的从你的程序中调用Lua函数Q?br />  lua.Call<void>("print", "Hello World");
  int sum = lua.Call<int>("add", 2, 3);
  q里Q?lt;> 里头的类型是q回值的cd?br />
5.  如何让Lua也能调用C++的函?br />  _N的地Ҏ(gu)了。假如有下面q样的一个函敎ͼ
  int add(int a, int b)
  {
    return a + b;
  }
  如果惌它能够让Lua使用Q只需它注册到Lua引擎当中可以了Q?br />  lua.RegisterFunc("add", int(int,int), add);
  q样QLua中就可以用直接用了Q?br />  QLua脚本Qsum = add(1, 3)

  (*) RegisterFunc的功能,是让你把C++的函数注册到Lua中,供Lua脚本使用?br />    W一个参敎ͼ是想要在Lua中用的函数名?br />    W二个参敎ͼ是C++中函数的原型Q?C++允许函数重蝲的,你可以用函数原型,来选择需要注册到Lua引擎中的那个函数?br />    W三个参敎ͼ是C++中函数的指针了?br />
6.  如何能让C++的类在Lua中?br />  我们先看看下面这个C++c:
class MyArray
{
  std::vector<double> array;
public:
  void setvalue(int index, double value);
  double getvalue(int index);
  int size();
  const char* ToString();
};

  你准备要让Lua能够自由讉Kq操作这个类。很单,你只需增加几个宏定义就可以了:

class MyArray
{
  std::vector<double> array;
public:
  void setvalue(int index, double value);
  double getvalue(int index);
  int size();
  const char* ToString();
  // 一?class 作ؓ一?Lua 对象是很Ҏ(gu)的,只需要增加以下宏定义?br />  DEFINE_TYPENAME("My.array");
  BEGIN_REGLUALIB("array")
      LUALIB_ITEM_create("new", MyArray )  // 创徏MyArray (注:׃发表的原因,create应ؓ全部大写)
      LUALIB_ITEM_DESTROY("del", MyArray )  // 消除MyArray?br />  END_REGLUALIB()
  BEGIN_REGLUALIB_MEMBER()
    LUALIB_ITEM_FUNC("size", int (MyArray*), &MyArray::size)
    LUALIB_ITEM_FUNC("__getindex", double(MyArray*, int), &MyArray::getvalue)  
    LUALIB_ITEM_FUNC("__newindex", void (MyArray*, int, double), &MyArray::setvalue)
    LUALIB_ITEM_FUNC("__tostring", const char* (MyArray*), &MyArray::ToString)
    LUALIB_ITEM_DESTROY("__gc", MyArray )   // 垃圾攉时消除对象用?br />  END_REGLUALIB_MEMBER()
};

  只要有了q些宏定义,q个cd是可以在Lua中用的cMQ我们就可以在Lua中注册这个类了:
  lua.Register<MyArray>()

  q样注册以后Q我们在Lua中就可以使用q个cMQ?br />  a = array.new()  -- 创徏对象Q相当于 a = new Myarray
  a[1] = 10  -- 调用__newindexQ也是C++中的 a->setvalue(1, 10)
  a[2] = 20  -- 调用__newindexQ也是C++中的 a->setvalue(2, 20)
  print(
    a,  -- 调用 __tostringQ也是C++中的 a->ToString()
    a:size(), -- 相当于C++中的 a->size()
    a[1], -- 调用__getindexQ也是C++中的a->getvalue(1)
    a[2]) --调用__getindexQ也是C++中的a->getvalue(2)
  array.del(a)  -- 清除对象Q相当于 delete a
  a = nil  -- 清空 aQ很象C++中的 a = NULL

  当然Q你也可以不用delq个对象Q而是{待Lua帮你自动q行垃圾回收。在Luaq行垃圾回收Ӟ它会自动调用q个对象?__gc Q相当于 delete?br />
  那么Q在C++中要创徏MyArray对象Qƈ且传递给Lua全局变量怎么办?p前面讲过的一P使用SetGlobalQ?br />  MyArray* a = new MyArray;
  lua.SetGlobal("a", a);
  要获取该对象Q同LQ应该用GetGlobalQ?br />  MyArray* a = lua.GetGlobal<MyArray>("a");
  
  对于传递给Lua的对象,pLua来管理该对象的生存周期好了。如果你非要删除它的话,你可以用DelGlobalObjectQ?br />  lua.DelGlobalObject<MyArray>("a");
  不过q么做的话,你应当明白你在做什么,因ؓ在Lua的脚本中Q可能已l在多处引用了这个对象了。删除了其中一个,导致其它引用对象失效,从而可能引致系l崩溃?br />
  (1)  DEFINE_TYPENAME("My.array");
    定义cd的名U。在Lua中,q个cd名称是唯一用来识别C++cd的,你必Mؓ不同的对象给予不同的名称?br />
  (2)  BEGIN_REGLUALIB("array") ?END_REGLUALIB()
    你可以ؓ一个对象定义一个程序库Q?array"是E序库的名字。在E序库中定义的函数是全局函数Q在Lua中,使用该函敎ͼ需要在函数前加上库的名字,如:array.newQ)。通常Q程序库会包含创建对象的Ҏ(gu)。如Q?br />    LUALIB_ITEM_create("new", MyArray )  // 创徏MyArray (注:׃发表的原因,create应ؓ全部大写)
    q样子,你才能在Lua中创建MyArrayQ?br />    a = array.new()
  
    你也可以选择增加一个删除对象操作:
    LUALIB_ITEM_DESTROY("del", MyArray )   // 删除MyArray
    q样Q你可以直接删除一个对象了Q?br />    array.del(a)

  (3)  BEGIN_REGLUALIB_MEMBER() …END_REGLUALIB_MEMBER()
    在此处,你可以定义对象的成员函数Q也可以重蝲对象的操作符——是的,pC++的operator重蝲。例如:
    LUALIB_ITEM_FUNC("__newindex", void (MyArray*, int, double), &MyArray::setvalue)
    是重蝲 operator[] 操作W。Lua中可重蝲的操作符q有许多Q如Q?br />
    __getindexQ操作符[]Q支持读取访问,?v = a[10]
    __newindexQ操作符[]Q支持赋D问,?a[10] = 1.22
    __tostringQ将变量转换成字串__addQ等同于operator +
    __addQ操作符 Q?br />    __subQ操作符 ?br />    __mulQ操作符 ×
    __divQ操作符 ÷
    __powQ操作符 ^ (乘方)
    __unmQ一元操作符 ?br />    __concatQ操作符 .. (字符串连?
    __eqQ操作符 == (a ~= b{h(hun)?not a == b)
    __ltQ操作符 < (a > b {h(hun)?b < a)
    __leQ操作符 <= (a >= b {h(hun)?b <= aQ要注意的是Q如果没有定?__le"Q则Lua会试a<=b 转换?not (b < a) )

    __gcQ在垃圾回收时调用此函数Q相当于C++的析构函数。强烈徏议定义此操作W,以免造成内存泄漏{情c比如:
    LUALIB_ITEM_DESTROY("__gc", MyArray )   // 垃圾攉时消除对象用?br />
    (? q里要说明一下,在lua中,讉K索引操作W是__indexQ不是__getindexQ在luaWrapper库中Qؓ了方便用,其映射为__getindexQ同Ӟ对__index的定义将会被忽略?br />
    p么简单。假如你已经有现成的c,而你没有修改该类的权力,如何其加入到Lua中呢Q答案就是,l承它,把zcd入到Lua中?br />
l束?br />  LuaWrapper 需要用到boost库的支持Qboost/type_traits.hpp, boost/function.hpp, boost/bind.hppQ它使用了C++的模杉K份特化,因此QC++~译器如果不支持此特性,无法编译。目前支持此Ҏ(gu)的~译器已l有很多。在VisualStudo产品pd中,只有VC7.1能支持此Ҏ(gu),因此Q?zhn)如果正在使用VisualStudioQ请认你用的是VisualStudio2003?br />  如果你觉?LuaWrapper For C++ 能够帮助你,我会感觉很荣q。我很愿意将q个E序库分享给大家。顺便一提的是,如果你在使用q程中发现BUGQ或是有好的Q希望?zhn)能与我联pR你在用过E中Q请不要删除文g中的|名信息Q如果你修改了程序库Q请(zhn)在修改的文件中加入(zhn)的修改说明。当Ӟ我会非常Ƣ迎(zhn)能修改后的程序回馈给我。我会l优化ƈ完善它?br />
=============================================================

File: Click Here Download: LuaWrapper For C++
File: Click Here Download: LuaWrapper test program

=============================================================



李锦?mybios) 2006-11-18 10:00 发表评论
]]>
【{贴】Lua E序设计初步http://www.shnenglu.com/mybios/archive/2006/11/18/15338.html李锦?mybios)李锦?mybios)Sat, 18 Nov 2006 01:48:00 GMThttp://www.shnenglu.com/mybios/archive/2006/11/18/15338.htmlhttp://www.shnenglu.com/mybios/comments/15338.htmlhttp://www.shnenglu.com/mybios/archive/2006/11/18/15338.html#Feedback0http://www.shnenglu.com/mybios/comments/commentRss/15338.htmlhttp://www.shnenglu.com/mybios/services/trackbacks/15338.html版权所有{载请注明原出?br />主页Q第二h?http://www.d2-life.com
   http://www.d2-life.com/LBS/blogview.asp?logID=39

  在这文章中Q我惛_大家介绍如何q行LuaE序设计。我假设大家都学q至一门编E语aQ比如Basic或CQ特别是C。因为Lua的最大用途是在宿ȝ序中作ؓ脚本使用的?br />  Lua 的语法比较简单,学习h也比较省力,但功能却q不弱?br />  在Lua中,一切都是变量,除了关键字。请Cq句话?br />
I.  首先是注?br />  写一个程序,L不了注释的?br />  在Lua中,你可以用单行注释和多行注释?br />  单行注释中,q箋两个减号"--"表示注释的开始,一直gl到行末为止。相当于C++语言中的"http://"?br />  多行注释中,?--[["表示注释开始,q且一直gl到"]]"为止。这U注释相当于C语言中的"/*?/"。在注释当中Q?[["?]]"是可以嵌套的?br />II.  Lua~程
  l典?Hello world"的程序L被用来开始介l一U语a。在Lua中,写一个这LE序很简单:
  print("Hello world")
  在Lua中,语句之间可以用分?Q?隔开Q也可以用空白隔开。一般来_如果多个语句写在同一行的话,L用分号隔开?br />  Lua 有好几种E序控制语句Q如Q?br />
  条g控制Qif 条g then ?elseif 条g then ?else ?end
  While循环Qwhile 条g do ?end
  Repeat循环Qrepeat ?until 条g
  For循环Qfor 变量 = 初|l点|步进 do ?end
  For循环Qfor 变量1Q变?Q?Q变量N in表或枚D函数 do ?end

  注意一下,for的@环变量L只作用于for的局部变量,你也可以省略步进|q时候,for循环会?作ؓ步进倹{?br />  你可以用break来中止一个@环?br />  如果你有E序设计的基Q比如你学过BasicQC之类的,你会觉得Lua也不难。但Lua有几个地Ҏ(gu)明显不同于这些程序设计语a的,所以请特别注意?br />
  Q语句块
    语句块在C++中是?{"?}"括v来的Q在Lua中,它是用do ?end 括v来的。比如:
    do print("Hello") end
    你可以在 函数 中和 语句?中定局部变量?br />
  Q赋D?br />    赋D句在Lua被强化了。它可以同时l多个变量赋倹{?br />    例如Q?br />    a,b,c,d=1,2,3,4
    甚至是:
    a,b=b,a  -- 多么方便的交换变量功能啊?br />    在默认情况下Q变量L认ؓ是全局的。假如你要定义局部变量,则在W一ơ赋值的时候,需要用local说明。比如:
    local a,b,c = 1,2,3  -- a,b,c都是局部变?br />
  Q数D?br />    和C语言一P支持 +, -, *, /。但Luaq多了一?^"。这表示指数乘方q算。比?^3 l果?, 2^4l果?6?br />    q接两个字符Ԍ可以?.."q处W。如Q?br />    "This a " .. "string." -- {于 "this a string"

  Q比较运?br />    < > <= >= == ~=
    分别表示 于Q大于,不大于,不小于,相等Q不相等
    所有这些操作符Lq回true或false?br />    对于TableQFunction和Userdatacd的数据,只有 == ?~=可以用。相{表CZ个变量引用的是同一个数据。比如:
    a={1,2}
    b=a
    print(a==b, a~=b)  -- true, false
    a={1,2}
    b={1,2}
    print(a==b, a~=b)  -- false, true

  Q逻辑q算
    and, or, not
    其中Qand ?or 与C语言区别特别大?br />    在这里,请先CQ在Lua中,只有false和nil才计ؓfalseQ其它Q何数据都计算为trueQ?也是trueQ?br />    and ?or的运结果不是true和falseQ而是和它的两个操作数相关?br />    a and bQ如果a为falseQ则q回aQ否则返回b
    a or bQ如?a 为trueQ则q回aQ否则返回b

    丑և个例子:
     print(4 and 5) --> 5
     print(nil and 13) --> nil
     print(false and 13) --> false
     print(4 or 5) --> 4
     print(false or 5) --> 5

    在Lua中这是很有用的特性,也是比较令hh的特性?br />    我们可以模拟C语言中的语句Qx = a? b : cQ在Lua中,可以写成Qx = a and b or c?br />    最有用的语句是Q?x = x or vQ它相当于:if not x then x = v end ?br />
  Q运符优先U,从高C序如下Q?br />    ^
    not - Q一元运)
     * /
     + -
     ..Q字W串q接Q?br />     < > <= >= ~= ==
     and
     or

III.  关键?br />  关键字是不能做ؓ变量的。Lua的关键字不多Q就以下几个Q?br />  and break do else elseif
  end false for function if
  in local nil not or
  repeat return then true until while

IV.  变量cd
  怎么定一个变量是什么类型的呢?大家可以用type()函数来检查。Lua支持的类型有以下几种Q?br />
  Nil  I|所有没有用过的变量,都是nil。nil既是|又是cd?br />  Boolean  布尔?br />  Number  数|在Lua里,数值相当于C语言的double
  String  字符Ԍ如果你愿意的话,字符串是可以包含'\0'字符?br />  Table  关系表类型,q个cd功能比较强大Q我们在后面慢慢说?br />  Function  函数cdQ不要怀疑,函数也是一U类型,也就是说Q所有的函数Q它本n是一个变量?br />  Userdata  嗯,q个cd专门用来和Lua的宿L交道的。宿主通常是用C和C++来编写的Q在q种情况下,Userdata可以是宿ȝL数据cdQ常用的有Struct和指针?br />  Thread    U程cdQ在Lua中没有真正的U程。Lua中可以将一个函数分成几部䆾q行。如果感兴趣的话Q可以去看看Lua的文档?br />
V.  变量的定?br />  所有的语言Q都要用到变量。在Lua中,不管你在什么地方用变量,都不需要声明,q且所有的q些变量L全局变量Q除非,你在前面加上"local"?br />  q一点要特别注意Q因Z可能惛_函数里用局部变量,却忘了用local来说明?br />  至于变量名字Q它是大写相关的。也是_A和a是两个不同的变量?br />  定义一个变量的Ҏ(gu)是赋倹{?Q?操作是用来赋值的
  我们一h定义几种常用cd的变量吧?br />  A.  Nil
    正如前面所说的Q没有用过的变量的|都是Nil。有时候我们也需要将一个变量清除,q时候,我们可以直接l变量赋以nil倹{如Q?br />    var1=nil  -- h?nil 一定要写

  B.  Boolean
    布尔值通常是用在进行条件判断的时候。布?yu)值有两种Qtrue ?false。在Lua中,只有false和nil才被计算为falseQ而所有Q何其它类型的|都是true。比?Q空串等{,都是true。不要被C语言的习惯所误导Q?在Lua中的的确是true。你也可以直接给一个变量赋以Booleancd的|如:
    varboolean = true

  C.  Number
    在Lua中,是没有整数类型的Q也不需要。一般情况下Q只要数g是很大(比如不超q?00,000,000,000,000Q,是不会生舍入误差的。在很多CPU上,实数的运ƈ不比整数慢?br />    实数的表C方法,同C语言cMQ如Q?br />    4 0.4 4.57e-3 0.3e12 5e+20

  D.  String
    字符ԌL一U非常常用的高cd。在Lua中,你可以非常方便的定义很长很长的字W串?br />    字符串在Lua中有几种Ҏ(gu)来表C,最通用的方法,是用双引h单引h括v一个字W串的,如:
    "This is a string."
    和C语言相同的,它支持一些{义字W,列表如下Q?br />    \a  bell
    \b  back space
    \f  form feed
    \n  newline
    \r  carriage return
    \t  horizontal tab
    \v  vertical tab
    \\  backslash
    \"  double quote
    \'  single quote
    \[  left square bracket
    \]  right square bracket

    ׃q种字符串只能写在一行中Q因此,不可避免的要用到转义字符。加入了转义字符的串Q看h实在是不敢恭l_比如Q?br />    "one line\nnext line\n\"in quotes\", 'in quotes'"
    一大堆?\"W号让h看v来很倒胃口。如果你与我有同感,那么Q我们在Lua中,可以用另一U表C方法:?[["?]]"多行的字符串括hQ如Q?br />    page = [[
    <HTML>
      <HEAD>
        <TITLE>An HTML Page</TITLE>
      </HEAD>
      <BODY>
        <A HREF="lua' target=_blank>http://www.lua.org">Lua</A>
        [[a text between double brackets]]
      </BODY>
    </HTML>
    ]]

    值得注意的是Q在q种字符串中Q如果含有单独用的"[["?]]"׃然得?\["?\]"来避免歧义。当Ӟq种情况是极会发生的?br />
  E.  Table
    关系表类型,q是一个很强大的类型。我们可以把q个cd看作是一个数l。只是C语言的数l,只能用正整数来作索引Q在Lua中,你可以用Lcd来作数组的烦引,除了nil。同P在C语言中,数组的内容只允许一U类型;在Lua中,你也可以用Q意类型的值来作数l的内容Q除了nil?br />    Table的定义很单,它的主要特征是用"{"?}"来括起一pd数据元素的。比如:

    T1 = {}  -- 定义一个空?br />    T1[1]=10  -- 然后我们可以象C语言一h使用它了?br />    T1["John"]={Age=27, Gender="Male"}
    q一句相当于Q?br />    T1["John"]={}  -- 必须先定义成一个表Q还记得未定义的变量是nilcd?br />    T1["John"]["Age"]=27
    T1["John"]["Gender"]="Male"
    当表的烦引是字符串的时候,我们可以写成Q?br />    T1.John={}
    T1.John.Age=27
    T1.John.Gender="Male"
    ?br />    T1.John{Age=27, Gender="Male"}
    q是一个很强的Ҏ(gu)?br />
    在定义表的时候,我们可以把所有的数据内容一起写?{"?}"之间Q这样子是非常方便,而且很好看。比如,前面的T1的定义,我们可以q么写:

    T1=
    {
      10,  -- 相当?[1] = 10
      [100] = 40,
      John=  -- 如果你原意,你还可以写成Q["John"] =
      {
        Age=27,   -- 如果你原意,你还可以写成Q["Age"] =27
        Gender=Male   -- 如果你原意,你还可以写成Q["Gender"] =Male
      },
      20  -- 相当?[2] = 20
    }

    看v来很漂亮Q不是吗Q我们在写的时候,需要注意三点:
    W一Q所有元素之_L用逗号"Q?隔开Q?br />    W二Q所有烦引值都需要用"["?]"括v来;如果是字W串Q还可以L引号和中括号Q?br />    W三Q如果不写烦引,则烦引就会被认ؓ是数字,q按序自动?往后编Q?br />
    表类型的构造是如此的方便,以致于常常被人用来代曉K|文件。是的,不用怀疑,它比ini文g要漂亮,q且强大的多?br />
  F.  Function
    函数Q在Lua中,函数的定义也很简单。典型的定义如下Q?br />    function add(a,b)  -- add 是函数名字,a和b是参数名?br />     return a+b  -- return 用来q回函数的运行结?br />    end

    h意,return语言一定要写在end之前。假如你非要在中间放上一句returnQ那么请写成Qdo return end?br />    q记得前面说q,函数也是变量cd吗?上面的函数定义,其实相当于:
    add = function (a,b) return a+b end
    当你重新ladd赋值时Q它?yu)׃再表C个函C。你甚至可以赋给addL数据Q包括nil Q这P你就清除了add变量Q。Function是不是很象C语言的函数指针呢Q?br />
    和C语言一PLua的函数可以接受可变参C敎ͼ它同h??来定义的Q比如:
    function sum (a,b,?
    如果惛_得…所代表的参敎ͼ可以在函C讉Ka(chn)rg局部变量(表类型)得到?br />    ?sum(1,2,3,4)
    则,在函CQa = 1, b = 2, arg = {3, 4}
    更可늚是,它可以同时返回多个结果,比如Q?br />    function s()
      return 1,2,3,4
    end
    a,b,c,d = s()  -- 此时Qa = 1, b = 2, c = 3, d = 4

    前面说过Q表cd可以拥有Lcd的|包括函数Q因此,有一个很强大的特性是Q拥有函数的表,哦,我想更恰当的应该说是对象吧。Lua可以使用面向对象~程了。不信?那我举例如下Q?br />
    t =
    {
     Age = 27
     add = function(self, n) self.Age = self.Age+n end
    }
    print(t.Age)  -- 27
    t.add(t, 10)
    print(t.Age)  -- 37

    不过Qt.add(t,10) q一句实在是有点土对吧?没关p,在Lua中,你可以简写成Q?br />    t:add(10)    -- 相当?t.add(t,10)

  G.  Userdata ?Thread
    q两个类型的话题Q超Z本文的内容,׃打算l说了?br />
VI.  l束?br />  p么结束了吗?当然不是Q接下来Q需要用Lua解释器,来帮助你理解和实践了。这小文只是帮助你大体了解Lua的语法。如果你有编E基Q相信会很快对Lua上手了?br />  pC语言一PLua提供了相当多的标准函数来增强语言的功能。用这些标准函敎ͼ你可以很方便的操作各U数据类型,q处理输入输出。有兌斚w的信息,你可以参考《Programming in Lua 》一书,你可以在|络上直接观看电(sh)子版Q网址为:http://www.lua.org/pil/index.html
  当然QLua的最强大的功能是能与宿主E序亲蜜无间的合作,因此Q下一文章,我会告诉大家Q如何在你的E序中用Lua语言作ؓ脚本Q你的E序和Lua脚本q行交互?br />

李锦?mybios) 2006-11-18 09:48 发表评论
]]>
【{贴】如何在C++中集成Lua脚本(LuaPlus? http://www.shnenglu.com/mybios/archive/2006/11/18/15337.html李锦?mybios)李锦?mybios)Sat, 18 Nov 2006 01:46:00 GMThttp://www.shnenglu.com/mybios/archive/2006/11/18/15337.htmlhttp://www.shnenglu.com/mybios/comments/15337.htmlhttp://www.shnenglu.com/mybios/archive/2006/11/18/15337.html#Feedback0http://www.shnenglu.com/mybios/comments/commentRss/15337.htmlhttp://www.shnenglu.com/mybios/services/trackbacks/15337.html

d我作了一个Lua脚本的C++包装Q有许多朋友感兴,q尝试用,我感到受宠若惊。事实上Q我作的包装Q学习的目的比较强,它还是有许多~陷的。ؓ了让朋友们少走弯路,我推荐用LuaPlus作ؓC++的包装?/p>

LuaPlus是Lua的C++增强Q也是_LuaPlus本n是在Lua的源码上q行增强得来的。用它与C++q行合作Q是比较好的一个选择?br />LuaPlus目前版本为:LuaPlus for Lua 5.01 Distribution Build 1080 (February 28, 2004)。大家可以到http://luaplus.org/ 站点下蝲Q?br />源码   (http://wwhiz.com/LuaPlus/LuaPlus50_Build1081.zip)
目标?(http://wwhiz.com/LuaPlus/LuaPlus50_Build1081_Win32Binaries.zip)

我将在下面说明,如何使用LuaPlusQ以及如何更方便的让LuaPlus与C++的类合作无间?/p>

1. 调用Lua脚本

    // 创徏Lua解释器:
    LuaStateOwner state;
   
    // 执行Lua脚本Q?br />    state->DoString("print('Hello World\n')");
    // 载入Lua脚本文gq执行:
    state->DoFile("C:\\test.lua");
    // 载入~译后的Lua脚本文gq执行:
    state->DoFile("C:\\test.luac");

2. 与Lua脚本互相调用

    // 为Lua脚本讄变量
    state->GetGlobals().SetNumber("myvalue", 123456);
    // 获得Lua变量的?br />    int myvalue = state->GetGlobal("myvalue").GetInteger();
   
    // 调用Lua函数
    LuaFunction<int> luaPrint = state->GetGlobal("print");
    luaPrint("Hello World\n");
   
    // 让Lua调用C语言函数
    int add(int a, int b){ return a+b;}
    state->GetGlobals().RegisterDirect("add", add);
    state->DoString("print(add(3,4))");
   
    // 让Lua调用C++cL员函?br />    class Test{public: int add(int a, int b){return a+b;}};
    Test test;
    state->GetGlobals().RegisterDirect("add", test, add);
    state->DoString("print(add(3,4))");
   
3. 在Lua脚本中用C++c?br />   
    q个E微有点麻烦。不q,我包装了一个LuaPlusHelper.h的文Ӟ它可以很L的完成这个工作。它的实C很简单,大家可以从源码上来获得如何用ULuaPlus实现同样的功能?br />    不过Q这里仍然有一个限制没有解冻I不能使用虚成员函数。不q考虑到我们仅是在Lua调用一下C++函数Qƈ不是要将C++完美的导入到LuaQ这个限制完全可以接受?br />    另外Q类成员变量不能直接在Lua中访问,可以通过cL员函数来讉KQ比如SetValue/GetValue之类)?/p>

 // 下面是一个简单的C++c?   
 class Logger
 {
 public:
  void LOGMEMBER(const char* message)
  {
   printf("In member function: %s\n", message);
  }
 
  Logger()
  {
   printf("Constructing(%p)...\n", this);
   v = 10;
  }
  virtual ~Logger()
  {
   printf("Destructing(%p)...\n", this);
  }
 
  Logger(int n)
  {
   printf(" -- Constructing[%d](%p)...\n", n, this);
  }
  Logger(Logger* logger)
  {
   printf(" -- Constructing[%p](%p)...\n", logger, this);
   logger->LOGMEMBER(" Call From Constructor\n");
  }
  int SetValue(int val)
  {
   v = val;
  }
  int GetValue()
  {
   return v;
  }
 public:
  int v;
 };

    // 导入到Lua脚本Q?br />    LuaClass<Logger>(state)
 .create("Logger") // 定义构造函?Logger::Logger()
 .create<int>("Logger2")  // 定义构造函?Logger::Logger(int)
 .create<Logger*>("Logger3") // 定义构造函?Logger::Logger(Logger*)
 .destroy("Free")  // 定义析构函数 Logger::~Logger()
 .destroy("__gc")  // 定义析构函数 Logger::~Logger()
 .def("lm", &Logger::LOGMEMBER)  // 定义成员函数 Logger::LOGMEMBER(const char*)
 .def("SetValue", &Logger::SetValue)
 .def("GetValue", &Logger::GetValue);
 
    // 在Lua中用Loggerc?1)Q?br />    state->DoString(
        "l = Logger();"  // 调用构造函?Logger::Logger()
        "l.lm('Hello World 1');"  // 调用成员函数 Logger::LOGMEMBER(const char*)
        "l.Free();"  // 调用析构函数 Logger::~Logger()
        );

    // 在Lua中用Loggerc?2)Q?br />    state->DoString(
        "m = Logger(10);" // 调用构造函?Logger::Logger(int)
        "m.lm('Hello World 2');"  // 调用成员函数 Logger::LOGMEMBER(const char*)
        "n = Logger(m);" // 调用构造函?Logger::Logger(Logger*)
        "n.lm('Hello World 3');"  // 调用成员函数 Logger::LOGMEMBER(const char*)
        "m.SetValue(11);"
        "print(m.GetValue());"
        "m,n = nil, nil;" // m,n 由Lua的垃极回收来调用析构函数
        );

4. 一lC函数归类到Lua模块

    //同上面一P我采用LuaPlusHelper.h来简化:
    LuaModule(state, "mymodule")
 .def("add", add)
 .def("add2", test, add);
 
    state->DoString(
        "print(mymodule.add(3,4));"
        "print(mymodule.add2(3,4));"
        );

5. 使用Lua的Table数据cd
    // 在Lua中创建Table
    LuaObject table = state->GetGlobals().CreateTable("mytable");
    table.SetInteger("m", 10);
    table.SetNumber("f", 1.99);
    table.SetString("s", "Hello World");
    table.SetWString("ch", L"你好");
    table.SetString(1, "What");
   
    // 相当于Lua中的Q?br />    // mytable = {m=10, f=1.99, s="Hello World", ch=L"你好", "What"}
   
    // 也可以用table作ؓkey和value:
    state->GetGlobals().CreateTable("nexttable")
        .SetString(table, "Hello")
        .SetObject("obj", table);
    // 相当于Lua中的Q?br />    // nexttable = {mytable="Hello", obj=mytable}
   
    //获得Table的内容:
    LuaObject t2 = state->GetGlobals("mytable");
    int m = t2.GetByName("m").GetInteger();
   
    LuaObject t3 = state->GetGlobals("nexttable");
    std::string str = t3.GetByObject(t2).GetString();
   
6  遍历Table

 LuaStateOwner state;
 state.DoString( "MyTable = { Hi = 5, Hello = 10, Yo = 6 }" );
 
 LuaObject obj = state.GetGlobals()[ "MyTable" ];
 for ( LuaTableIterator it( obj ); it; it.Next() )
 {
     const char* key = it.GetKey().GetString();
     int num = it.GetValue().GetInteger();
 }

上面我只是简单的举一些例子来说明LuaPlus以及LuaPlusHelper的用方法,具体文档请参见LuaPlus?/p>

需要下载LuaPlusHelperQ请点这里:
http://www.d2-life.com/LBS/attachments/month_200509/06_zwo3LuaPlusHelper.zip



李锦?mybios) 2006-11-18 09:46 发表评论
]]>
【{贴】?Lua ~写可嵌入式脚本http://www.shnenglu.com/mybios/archive/2006/11/18/15336.html李锦?mybios)李锦?mybios)Sat, 18 Nov 2006 01:39:00 GMThttp://www.shnenglu.com/mybios/archive/2006/11/18/15336.htmlhttp://www.shnenglu.com/mybios/comments/15336.htmlhttp://www.shnenglu.com/mybios/archive/2006/11/18/15336.html#Feedback0http://www.shnenglu.com/mybios/comments/commentRss/15336.htmlhttp://www.shnenglu.com/mybios/services/trackbacks/15336.html

使用 Lua ~写可嵌入式脚本

Lua 提供了高U抽象,却又没失Mg的关?/p>

未显C需?JavaScript 的文档选项



U别: 初

Martin Streicher (martin.streicher@linux-mag.com), 首席~辑, Linux Magazine

2006 q?6 ?12 ?/p>

虽然~译性编E语a和脚本语a各自h自己独特的优点,但是如果我们使用q两U类型的语言来编写大型的应用E序会是什么样子呢QLua 是一U嵌入式脚本语言Q它非常,速度很快Q功能却非常强大。在创徏其他配置文g或资源格式(以及与之对应的解析器Q之前,请尝试一?Lua?/blockquote>

管诸如 Perl、Python、PHP ?Ruby 之类的解释性编E语a日益?Web 应用E序q泛地采U?—?它们已经长期用来实现自动化系l管理Q?—?但是诸如 C、C++ 之类的编译性编E语a依然是必需的。编译性编E语a的性能是脚本语a所无法企及的(只有手工调优的汇~程序的性能才能过它)Q有些Y?—?包括操作pȝ和设备驱动程?—?只能使用~译代码来高效地实现。实际上Q当软g和硬仉要进行无~地q接操作ӞE序员本能地׃选择 C ~译器:C 非常基础Q距?“原始金属材料非常近?—?卛_以操作硬件的很多Ҏ(gu)?—?q且 C 的表现力非常强大Q可以提供高U编E结构,例如l构、@环、命名变量和作用域?/p>

然而,脚本语言也有自己独特的优炏V例如,当某U语a的解释器被成功移植到一U^C以后Q用这U语a~写的大量脚本就可以不加M修改在这U新q_上运?—?它们没有诸如pȝ特定的函数库之类的依赖限制。(我们可以考虑一?Microsoft] Windows] 操作pȝ上的许多 DLL 文g?UNIX] ?Linux] 上的很多 libcsQ。另外,脚本语言通常都还会提供高U编E构造和便利的操作,E序员可以用这些功能来提高生效率和灵zL。另外,使用解释语言来编E的E序员工作的速度更快Q因不需要编译和链接的步骤。C 及其cM语言中的 “编码、编译、链接、运行?周期~减成了更ؓ紧凑?“编写脚本、运行”?/p>

Lua 新特?/font>

与其他脚本语a一PLua 也有自己的一些特性:

  • Lua cd?/b>?Lua 中,值可以有cdQ但是变量的cd都是动态决定的?i>nil、布?yu)型、数?/i> ?字符?/i> cd的工作方式与我们期望的一栗?
    • Nil 是gؓ nil 的一U特D类型,用来表示没有倹{?
    • 布尔型的值可以是 true ?false 帔R。(Nil 也可以表C?falseQQ何非 nil 的值都表示 true。)
    • Lua 中所有的数字都是双精度的Q不q我们可以非常简便地~写一些代码来实现其他数字cdQ?
    • 字符串是定长字符数组。(因此Q要在一个字W串后面附加上字W,必须对其q行拯。)
  • 表、函?/i> ?i>U程 cd都是引用。每个都可以赋值给一个变量,作ؓ参数传递,或作回g函数中返回。例如,下面是一个存储函数的例子Q?br />
    -- example of an anonymous function
    -- returned as a value
    -- see http://www.tecgraf.puc-rio.br/~lhf/ftp/doc/hopl.pdf
    function add(x)
      return function (y) return (x + y) end
    end
    f = add(2)
    print(type(f), f(10))
    function  12
    

  • Lua U程?/b>U程是通过调用内嵌函数 coroutine.create(f) 创徏的一?i>协同例程 (co-routine)Q其?f 是一?Lua 函数。线E不会在创徏时启动;相反Q它是在创徏之后使用 coroutine.resume(t) 启动的,其中 t 是一个线E。每个协同例E都必须使用 coroutine.yield() 偶尔获得其他协同例程的处理器?
  • 赋D句?/b>Lua 允许使用多种赋D句,可以先对表达式进行求|然后再进行赋倹{例如,下面的语句:

    i = 3
    a = {1, 3, 5, 7, 9}
    i, a[i], a[i+1], b = i+1, a[i+1], a[i]
    print (i, a[3], a[4], b, I)
    

    会生?4 7 5 nil nil。如果变量列表的个数大于值列表的个数Q那么多出的变量都被赋gؓ nilQ因此,b 是 nil。如果值的个数多于变量的个敎ͼ那么多出的值部分就会简单地丢弃。在 Lua 中,变量名是大小写敏感的Q这可以解释Z?I 的值是 nil?
  • 块(ChunkQ?/b> ?/i> 可以是Q?Lua 语句序列。块可以保存到文件中Q或者保存到 Lua E序中的字符串中。每个块都是作ؓ一个匿名函C来执行的。因此,块可以定义局部变量和q回倹{?
  • 更酷的东ѝ?/b>Lua h一个标?清理垃圾攉器。在 Lua 5.1 中,垃圾攉器是以增量方式工作的。Lua h完整的词法闭包(q与 Scheme cMQ而与 Python 不同Q。Lua h可靠的尾部调用语义(同样Q这也与 Scheme cMQ而与 Python 不同Q?

?Programming in Lua ?Lua-users wiki Q链接请参见后面?参考资?/font> 部分Q中可以扑ֈ更多 Lua 代码的例子?/p>

在所有的工程d中,要在~译性语a和解释性语a之间作出选择Q就意味着要在q种环境中对每种语言的优~点、权重和折中q行评测Qƈ接受所带来的风险?/p>



回页?/font>


在两个世界之间最好地q行混合

如果(zhn)希望充分利用这两个世界的优点,应该怎样办呢Q是选择最好的性能q是选择高强大的抽象?更进一步说Q如果我们希望对处理器密集且依赖于系l的法和函C及与pȝ无关且很Ҏ(gu)Ҏ(gu)需要而进行修改的单独逻辑q行优化Q那又当如何呢?

寚w性能代码和高U编E的需要进行^衡是 LuaQ一U可嵌入式脚本语aQ要解决的问题。在需要时我们可以使用~译后的代码来实现底层的功能Q然后调?Lua 脚本来操作复杂的数据。由?Lua 脚本是与~译代码独立的,因此我们可以单独修改q些脚本。?LuaQ开发周期就非常cM?“编码、编译、运行、编写脚本、编写脚本、编写脚?...”?/p>

例如QLua Web 站点 “用?面Q请参见 参考资?/font>Q列ZL市场上的几个计算机游戏,包括 World of Warcraft 和(家用版的Q?i>DefenderQ它们集?Lua 来实现很多东西,从用L面到敌h的h工智能都可以。Lua 的其他应用程序包括流行的 Linux 软g更新工具 apt-rpm 的扩展机Ӟq有 “Crazy Ivan?Robocup 2000 冠军联赛的控刉辑。这个页面上的很多推荐感a都对 Lua 的小巧与杰出性能赞不l口?/p>



回页?/font>


开始?Lua

Lua 5.0.2 版本是撰写本文时的最新版本,不过最q刚刚发布了 5.1 版本。?zhn)可以?lua.org 上下?Lua 的源代码Q在 Lua-users wikiQ链接请参见 参考资?/font>Q上可以扑ֈ预先~译好的二进制文件。完整的 Lua 5.0.2 核心文g中包括了标准库和 Lua ~译器,不过只有 200KB 大小?/p>

如果(zhn)用的?Debian LinuxQ那么可以以用户的n份运行下面的命o来快速安?Lua 5.0Q?/p>
# apt-get install lua50

本文中给出的例子都是?Debian Linux Sarge 上运行的Q用的?Lua 5.0.2 ?2.4.27-2-686 版本?Linux 内核?/p>

在系l上安装?Lua 之后Q我们可以首先来试用一下单独的 Lua 解释器。(所有的 Lua 应用E序必须要嵌入到宿主应用E序中。解释器只是一U特D类型的宿主Q对于开发和调试工作来说非常有用。)创徏一个名?factorial.lua 的文Ӟ然后输入下面的代码:

-- defines a factorial function
function fact (n)
  if n == 0 then
    return 1
  else
    return n * fact(n-1)
  end
end

print("enter a number:")
a = io.read("*number")
print(fact(a))

factorial.lua 中的代码 —?更确切地说是M Lua 语句序列 —?都称Z?i>?/i>Q这在上面的 Lua Ҏ(gu)?/font> 中已l进行了介绍。要执行刚才创徏的代码块Q请q行命o lua factorial.luaQ?/p>
$ lua factorial.lua
enter a number:
10
3628800

或者像在其他解释性语a中一P我们可以在代码顶部添加一?“标识符”(#!Q,使这个脚本变成可执行的,然后像单独命令一hq行q个文gQ?/p>
$ (echo '#! /usr/bin/lua'; cat factorial.lua) > factorial 
$ chmod u+x factorial
$ ./factorial
enter a number:
4
24





回页?/font>


Lua 语言

Lua hC脚本语言中的很多便利Q作用域Q控制结构,q代器,以及一l用来处理字W串、生及攉数据和执行数学计操作的标准库。在 Lua 5.0 Reference Manual 中有?Lua 语言的完整介l(请参?参考资?/font>Q?/p>

?Lua 中,只有?/i> hcdQ而变量的cd是动态决定的。Lua 中的基本cdQ|?8 U: nilQ布?yu)型Q数字,字符Ԍ函数Q线E,?/i> 以及 用户数据。前 6 U类型基本上是自描述的(例外情况请参见上面的 Lua Ҏ(gu)?/font> 一节)Q最后两个需要一点解释?/p>

Lua ?/font>

?Lua 中,表是用来保存所有数据的l构。实际上Q表?Lua ?i>惟一?/i> 数据l构。我们可以将表作为数l、字典(也称?i>散列 ?i>联合数组Q、树、记录,{等?/p>

与其他编E语a不同QLua 表的概念不需要是异构的:表可以包含Q何类型的l合Q也可以包含cLl元素和cd典元素的混合体。另外,M Lua ?—?包括函数或其他表 —?都可以用作字典元素的键倹{?/p>

要对表进行浏览,请启?Lua 解释器,q输入清?1 中的黑体昄的代码?/p>
清单 1. 体验 Lua ?/b>
$ lua
> -- create an empty table and add some elements
> t1 = {}
> t1[1] = "moustache"
> t1[2] = 3
> t1["brothers"] = true

> -- more commonly, create the table and define elements
> all at once
> t2 = {[1] = "groucho", [3] = "chico", [5] = "harpo"}
> t3 = {[t1[1]] = t2[1], accent = t2[3], horn = t2[5]}
> t4 = {}
> t4[t3] = "the marx brothers"
> t5 = {characters = t2, marks = t3}
> t6 = {["a night at the opera"] = "classic"}

> -- make a reference and a string
> i = t3
> s = "a night at the opera"

> -- indices can be any Lua value
> print(t1[1], t4[t3], t6[s])
moustache   the marx brothers classic

> -- the phrase table.string is the same as table["string"]
> print(t3.horn, t3["horn"])
harpo   harpo

> -- indices can also be "multi-dimensional"
> print (t5["marks"]["horn"], t5.marks.horn)
harpo   harpo

> -- i points to the same table as t3
> = t4[i]
the marx brothers

> -- non-existent indices return nil values
> print(t1[2], t2[2], t5.films)
nil     nil     nil

>  -- even a function can be a key 
> t = {}
> function t.add(i,j)
>> return(i+j)
>> end
> print(t.add(1,2))
3
> print(t['add'](1,2))
3
>  -- and another variation of a function as a key 
> t = {}
> function v(x)
>> print(x)
>> end
> t[v] = "The Big Store"
> for key,value in t do key(value) end
The Big Store

正如我们可能期望的一PLua q提供了很多q代器函数来对表q行处理。全局变量 table 提供了这些函敎ͼ是的QLua 包就是表Q。有些函敎ͼ例如 table.foreachi()Q会期望一个从 1Q数?1Q开始的q箋整数范围Q?/p>
> table.foreachi(t1, print)
1 moustache
2 3

另外一些函敎ͼ例如 table.foreach()Q会Ҏ(gu)个表q行q代Q?/p>
> table.foreach(t2,print)
1       groucho
3       chico
5       harpo
> table.foreach(t1,print)
1       moustache
2       3
brothers        true

管有些q代器对整数索引q行了优化,但是所有P代器都只单地处理 (key, value) 寏V?/p>

现在我们可以创徏一个表 tQ其元素?{2, 4, 6, language="Lua", version="5", 8, 10, 12, web="www.lua.org"}Q然后运?table.foreach(t, print) ?table.foreachi(t, print)?/p>

用户数据

׃ Lua 是ؓ了嵌入到使用另外一U语aQ例?C ?C++Q编写的宿主应用E序中,q与宿主应用E序协同工作Q因此数据可以在 C 环境?Lua 之间q行׃n。正?Lua 5.0 Reference Manual 所_userdata cd允许我们?Lua 变量中保存Q意的 C 数据。我们可以认?userdata 是一个字节数l?—?字节可以表示指针、结构或宿主应用E序中的文g?/p>

用户数据的内Ҏ(gu)自于 CQ因此在 Lua 中不能对其进行修攏V当Ӟ׃用户数据源自?CQ因此在 Lua 中也没有对用h据预定义操作。不q我们可以用另外一U?Lua 机制来创建对 userdata q行处理的操作,q种机制UCؓ 元表QmetatableQ?/i>

元表

׃表和用户数据都非常灵z,因此 Lua 允许我们重蝲q两U类型的数据的操作(不能重蝲其他 6 U类型)?i>元表 是一个(普通的QLua 表,它将标准操作映射成我们提供的函数。元表的键值称?i>事gQ|换而言之就是函敎ͼUCؓ元方?/i>?/p>

函数 setmetatable() ?getmetatable() 分别对对象的元表q行修改和查询。每个表?userdada 对象都可以具有自q元表?/p>

例如Q添加操作对应的事g?__add。我们可以推断这D代码所做的事情么?

-- Overload the add operation
-- to do string concatenation
--
mt = {}

function String(string)
  return setmetatable({value = string or ''}, mt)
end

-- The first operand is a String table
-- The second operand is a string
-- .. is the Lua concatenate operator
--
function mt.__add(a, b)
  return String(a.value..b)
end

s = String('Hello')
print((s + ' There ' + ' World!').value )

q段代码会生下面的文本Q?/p>
Hello There World!

函数 String() 接收一个字W串 stringQ将其封装到一个表Q?code>{value = s or ''}Q中Qƈ元?mt 赋值给q个表。函?mt.__add() 是一个元Ҏ(gu)Q它?yu)字W串 b d到在 a.value 中找到的字符串后?b ơ。这行代?print((s + ' There ' + ' World!').value ) 调用q个元方法两ơ?/p>

__index 是另外一个事件?code>__index 的元Ҏ(gu)每当表中不存在键值时׃被调用。下面是一个例子,它记?(memoize) 函数的|

-- code courtesy of Rici Lake, rici@ricilake.net
function Memoize(func, t)
  return setmetatable(
     t or {},
    {__index =
      function(t, k)
        local v = func(k);
        t[k] = v;
        return v;
        end
    }
  )
end

COLORS = {"red", "blue", "green", "yellow", "black"}
color = Memoize(
  function(node)
    return COLORS[math.random(1, table.getn(COLORS))]
    end
)

这D代码放?Lua 解释器中Q然后输?print(color[1], color[2], color[1])。?zhn)会看到cM?blue black blue 的内宏V?/p>

q段代码接收一个键?nodeQ查?node 指定的颜艌Ӏ如果这U颜色不存在Q代码就会给 node 赋一个新的随机选择的颜艌Ӏ否则,p回赋l?node 的颜艌Ӏ在前一U情况中Q?code>__index 元方法被执行一ơ以分配一个颜艌Ӏ后一U情冉|较简单,所执行的是快速散列查找?/p>

Lua 语言提供了很多其他功能强大的Ҏ(gu),所有这些特性都有很好的文档q行介绍。在到问题或希望与专家q行交谈Ӟ误?Lua Users Chat Room IRC ChannelQ请参见 参考资?/font>Q获得非常热心的支持?/p>



回页?/font>


嵌入和扩?/font>

除了语法单ƈ且具有功能强大的表结构之外,Lua 的强大功能其可以与宿主语言混合使用。由?Lua 与宿主语a的关p非常密切,因此 Lua 脚本可以对宿主语a的功能进行扩充。但是这U融合是双赢的:宿主语言同时也可以对 Lua q行扩充。D例来_C 函数可以调用 Lua 函数Q反之亦然?/p>

Lua 与宿主语a之间的这U共生关pȝ核心是宿主语a是一?i>虚拟堆栈。虚拟堆栈与实际堆栈cMQ是一U后q先出(LIFOQ的数据l构Q可以用来时存储函数参数和函数l果。要?Lua 中调用宿主语a的函敎ͼ反之亦然Q,调用者会一些值压入堆栈中Qƈ调用目标函数Q被调用的函C弹出q些参数Q当然要对类型和每个参数的D行验证)Q对数据q行处理Q然后将l果攑օ堆栈中。当控制q回l调用程序时Q调用程序就可以从堆栈中提取回倹{?/p>

实际上在 Lua 中用的所有的 C 应用E序~程接口QAPIQ都是通过堆栈来进行操作的。堆栈可以保?Lua 的|不过值的cd必须是调用程序和被调用者都知道的,特别是向堆栈中压入的值和从堆栈中弹出的值更是如此(例如 lua_pushnil() ?lua_pushnumber()?/p>

清单 2 l出了一个简单的 C E序Q节选自 参考资?/font> ?Programming in Lua 一书的W?24 章)Q它实现了一个很但却功能完善的 Lua 解释器?/p>
清单 2. 一个简单的 Lua 解释?/b>
 1 #include <stdio.h>
 2 #include <lua.h>
 3 #include <lauxlib.h>
 4 #include <lualib.h>
 5
 6 int main (void) {
 7   char buff[256];
 8   int error;
 9   lua_State *L = lua_open();   /* opens Lua */
10   luaopen_base(L);             /* opens the basic library */
11   luaopen_table(L);            /* opens the table library */
12   luaopen_io(L);               /* opens the I/O library */
13   luaopen_string(L);           /* opens the string lib. */
14   luaopen_math(L);             /* opens the math lib. */
15
16   while (fgets(buff, sizeof(buff), stdin) != NULL) {
17     error = luaL_loadbuffer(L, buff, strlen(buff), "line") ||
18             lua_pcall(L, 0, 0, 0);
19     if (error) {
20       fprintf(stderr, "%s", lua_tostring(L, -1));
21       lua_pop(L, 1);  /* pop error message from the stack */
22     }
23   }
24
25   lua_close(L);
26   return 0;
27 }

W?2 行到W?4 行包括了 Lua 的标准函敎ͼ几个在所?Lua 库中都会使用的方便函C及用来打开库的函数。第 9 行创Z一?Lua 状?/i>。所有的状态最初都是空的;我们可以使用 luaopen_...() 函数库d到状态中Q如W?10 行到W?14 行所C?/p>

W?17 行和 luaL_loadbuffer() 会从 stdin 中以块的形式接收输入Qƈ对其q行~译Q然后将其放入虚拟堆栈中。第 18 行从堆栈中弹出数据ƈ执行之。如果在执行时出C错误Q就向堆栈中压入一?Lua 字符丌Ӏ第 20 行访问栈Ӟ栈顶的烦引ؓ -1Q作?Lua 字符Ԍ打印消息Q然后从堆栈中删除该倹{?/p>

使用 C APIQ我们的应用E序也可以进?Lua 状态来提取信息。下面的代码片段?Lua 状态中提取两个全局变量Q?/p>
..
if (luaL_loadfile(L, filename) || lua_pcall(L, 0, 0, 0))
  error(L, "cannot run configuration file: %s", lua_tostring(L, -1));

lua_getglobal(L, "width");
lua_getglobal(L, "height");
..
width = (int) lua_tonumber(L, -2);
height = (int) lua_tonumber(L, -1);
..

请再ơ注意传输是通过堆栈q行的。从 C 中调用Q?Lua 函数与这D代码类|使用 lua_getglobal() 来获得函敎ͼ参数压入堆栈,调用 lua_pcall()Q然后处理结果。如?Lua 函数q回 n 个|那么W一个值的位置在堆栈的 -n 处,最后一个值在堆栈中的位置?-1?/p>

反之Q在 Lua 中调?C 函数也与之类伹{如果?zhn)的操作系l支持动态加载,那么 Lua 可以Ҏ(gu)需要来动态加载ƈ调用函数。(在必M用静态加载的操作pȝ中,可以?Lua 引擎q行扩充Q此时调?C 函数旉要重新编?Lua。)





回页?/font>


l束?/font>

Lua 是一U学习v来容易得难以|信的语aQ但是它单的语法却掩C了其强大的功能:q种语言支持对象Q这?Perl cMQ,元表使表cdh相当E度的可伸展性,C API 允许我们在脚本和宿主语言之间q行更好的集成和扩充。Lua 可以?C、C++、C#、Java??Python 语言中用?/p>

在创建另外一个配|文件或资源格式Q以及相应的处理E序Q之前,请尝试一?Lua。Lua 语言及其C֌非常健壮Q具有创新精,随时准备好提供帮助?/p>



回页?/font>


参考资?

学习

获得产品和技?/b>
  • 下蝲 Lua 5.0.2 ?Lua 5.1 源代码,从头开始编?Lua?

  • ?Lua-users wiki 上,览很多预先构徏的、可安装?Lua 二进制文件?

  • ?LuaForge 上可以找到大量的代码库,包括很多语言l定和专门的计算库?

  • 订购免费?SEK for Linux Q这有两?DVDQ包括最新的 IBM for Linux 试用软gQ包?DB2]、Lotus]、Rational]、Tivoli] ?WebSphere]?

  • 在?zhn)的下一个开发项目中采用 IBM 试用软gQ这可以?developerWorks 直接下蝲?


讨论






关于作?/font>

Martin Streicher ?Linux Magazine 的首席编辑。他在普渡大学获得了计算机硕士学位,?1982 q以来,׃直在使用 Pascal、C、Perl、Java 以及Q最q用的QRuby ~程语言~写c?Unix pȝ?/p>



李锦?mybios) 2006-11-18 09:39 发表评论
]]>
【{贴】Lua 5.0 参考手?http://www.shnenglu.com/mybios/archive/2006/11/18/15335.html李锦?mybios)李锦?mybios)Sat, 18 Nov 2006 01:37:00 GMThttp://www.shnenglu.com/mybios/archive/2006/11/18/15335.htmlhttp://www.shnenglu.com/mybios/comments/15335.htmlhttp://www.shnenglu.com/mybios/archive/2006/11/18/15335.html#Feedback2http://www.shnenglu.com/mybios/comments/commentRss/15335.htmlhttp://www.shnenglu.com/mybios/services/trackbacks/15335.html阅读全文

李锦?mybios) 2006-11-18 09:37 发表评论
]]>
【{贴】Lua常用资源q接(来自lua-users) http://www.shnenglu.com/mybios/archive/2006/11/18/15334.html李锦?mybios)李锦?mybios)Sat, 18 Nov 2006 01:35:00 GMThttp://www.shnenglu.com/mybios/archive/2006/11/18/15334.htmlhttp://www.shnenglu.com/mybios/comments/15334.htmlhttp://www.shnenglu.com/mybios/archive/2006/11/18/15334.html#Feedback0http://www.shnenglu.com/mybios/comments/commentRss/15334.htmlhttp://www.shnenglu.com/mybios/services/trackbacks/15334.html
  • 官方资源 
  • LuaC֌ 
  • Lua 文档
    • [Lua架构] - 描述了Lua的业务驱动方式,目的以及架构解决Ҏ(gu)?/li>
  • 带有例证的Lua文档
  • Lua 教程
  • 认证考试 
  • Benchmarks
  • 语言比较 
  • Lua 其他相关站点


  • 李锦?mybios) 2006-11-18 09:35 发表评论
    ]]>
    ˾Ʒþһ| þóСƵ| þùѹۿƷ| þ99Ʒþþþþ9| ëƬþþþþùëƬ| ɫۺϾžþ| þþҹƷ| ˾þۺߴý| þþƷ | þѸƵ| þþƷѲ| ޳ɫwwwþվҹ| 91Ըߺþþþ| þþƷĻ| ĻƷѾþ| 99þ99ֻѷѾƷ| ҹþþþþþþþ | þþһƷ99þþƷ66| Ʒþþþ| 97Ʒ˾þþô߽97| þ޾Ʒۿ| 97þþƷһ| 77777ҹþö| þԭƷ| 2021ٸþþþþþþþ| 뾫Ʒþþþ..| ޹ƷۺϾþ| ƷŮþþ| þþƷһ99| 99þþƷһ | 99þùһ| þۺɫһ| ޹˾þþƷ99| ھƷþþþav| ޹Ʒ˾þ| һһþaþۺϾƷ| Ļձ޾þþ| þþþþùƷŮ| þþƷhþþƷ帣ӰԺ1421 | þþþþþþþþþþþ| 99þþƷһѿ|