??xml version="1.0" encoding="utf-8" standalone="yes"?>久久精品国产2020,久久这里的只有是精品23,中文国产成人精品久久亚洲精品AⅤ无码精品 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 地图~辑器原理(关键是脚本)(j)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的地囄辑器使用?jin)一个文件来代表一个地图,地图里包含了(jin)什么东西?我无从得知,但是Q从他的~辑器上看,看到~辑器能对地图修改的东西Q就可以大概猜想到有哪些东西。仔l看地图~辑器,看到有那么几个模块:(x)地Ş~辑器、开关编辑器、声音编辑器、物体编辑器、战役编辑器、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="yogoykc" 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="seocgig" class="kw1">for</span> k1,v1 <span id="segimui" class="kw1">in</span><span id="ysmimyg" class="kw1">pairs</span><span id="mqsuymk" class="br0">(</span>tbl<span id="uoacwcu" class="br0">)</span><span id="maceoec" class="kw1">do</span><span id="uwqsmus" class="kw1">for</span> k2,v2 <span id="gaciksa" class="kw1">in</span><span id="ykmgyyw" class="kw1">pairs</span><span id="wykmqom" class="br0">(</span>v1<span id="cgycems" class="br0">)</span><span id="ykcgaog" class="kw1">do</span> ... <span id="scoquii" class="kw1">end</span> end</pre><br /><br />q里Qpairs 其实是一个全局变量应用的函数。如果我们这样做Q?br /><pre class="code"><span id="ikoqcqy" class="kw1">do</span><span id="kgqmowm" class="kw1">local</span><span id="oiceqow" class="kw1">pairs</span>=pairs <span id="smwqucq" class="kw1">for</span> k1,v1 <span id="mwykukw" class="kw1">in</span><span id="eocgiyw" class="kw1">pairs</span><span id="mgkcwok" class="br0">(</span>tbl<span id="iceysao" class="br0">)</span><span id="coqugwc" class="kw1">do</span><span id="ieoakky" class="kw1">for</span> k2,v2 <span id="myamgwm" class="kw1">in</span><span id="oimwqgw" class="kw1">pairs</span><span id="oicwigo" class="br0">(</span>v1<span id="umwqssq" class="br0">)</span><span id="yaeoige" class="kw1">do</span> ... <span id="seoiumc" class="kw1">end</span><span id="smyakcy" class="kw1">end</span> end</pre><br /><br />效率?x)稍微提高?sh)些。如果是单层循环Q这样做没有意义。因?for ... in 循环中的 pairs q个函数只会(x)被调用一ơ,而不是每ơ@环都去调。我们的原则其实是,被多ơ读取的 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会(x)产生新的对象。这是由 lua 本n?string 理机制D的。lua ?VM 内对相同?string 永远只保留一份唯一 copy Q这P所有字W串比较?yu)可以简化ؓ(f)地址比较。这也是 lua ?table 工作很快的原因之一。这U?string 理的策略,?java {一P所以跟 java 一P应该量避免在@环内不断的连接字W串Q比?a = a..x q样。每ơ运行,都很可能?x)生成一份新?copy ?br /><br />同样Q记住,每次构造一?table 都会(x)多一?table ?copy 。比如在 lua 里,把^面坐标封装成 { x, y } 用于参数传递,需要考虑q个问题。每ơ你x(chng)造一个坐标对象传递给一个函敎ͼ{ 10,20 } (tng) (tng)q样明确的写出,都会(x)构造一个新?table 出来。要么,我们惛_法考虑 table 的重用;要么Q干脆用 x,y 两个参数传递坐标?br /><br />同样需要注意的是以 function foo (...) q种方式定义函数Q?... q种不定参数Q每ơ调用的时候都?x)被定义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> 上面提到装坐标的问题。诚?dng)我们可以?{ x=1,y=2 } q样装一个坐标。不q还有一个方法可供选择。它E微轻量一炏V?br /><br /><pre class="code"><span id="gamgqqw" class="kw1">function</span> point <span id="wikgyqe" class="br0">(</span>x,y<span id="uoscgwc" class="br0">)</span><span id="ykysuas" class="kw1">return</span><span id="oqkeomc" class="kw1">function</span><span id="aewqksq" class="br0">(</span><span id="osugsqq" class="br0">)</span><span id="ikyauka" class="kw1">return</span> x,y <span id="mwakmci" class="kw1">end</span> end  (tng) <span id="kmqiuaq" class="co1">-- 使用范例</span> p=point<span id="smgauka" class="br0">(</span><span id="yqmgkai" class="nu0">1</span>,<span id="kegauka" class="nu0">2</span><span id="gseysyo" class="br0">)</span><span id="aeqcwmk" class="kw1">print</span><span id="ogceemk" class="br0">(</span>p<span id="qkgqmss" class="br0">(</span><span id="mgycmmc" class="br0">)</span><span id="imeqkyo" class="br0">)</span><span id="uoyswcs" class="co1">-- 输出 1 2 </span>  (tng)</pre><br /><br />如果你愿意,q可以做的复杂一点:(x)<br /><pre class="code"><span id="ueysuca" class="kw1">function</span> point <span id="wyquocs" class="br0">(</span>x,y<span id="kmyceuk" class="br0">)</span><span id="eaaeywu" class="kw1">return</span><span id="ymoogiy" class="kw1">function</span><span id="ugkegwm" class="br0">(</span>idx<span id="wsugiio" class="br0">)</span><span id="mikqock" class="kw1">if</span> idx==<span id="mauewmk" class="st0">"x"</span><span id="cougaao" class="kw1">then</span><span id="uwauwmk" class="kw1">return</span> x <span id="auoacka" class="kw1">elseif</span> idx==<span id="wsmyiye" class="st0">"y"</span><span id="wikoiow" class="kw1">then</span><span id="oqcmiye" class="kw1">return</span> y <span id="awqkwuc" class="kw1">else</span><span id="cuyickk" class="kw1">return</span> x,y <span id="qaeiaig" class="kw1">end</span><span id="wgoueuk" class="kw1">end</span> end  (tng) <span id="kcoasig" class="co1">-- 使用范例</span> p=point<span id="mqsmgom" class="br0">(</span><span id="amqcwuk" class="nu0">1</span>,<span id="auoacqi" class="nu0">2</span><span id="uwgsomk" class="br0">)</span><span id="imwqkio" class="kw1">print</span><span id="eqkmqaq" class="br0">(</span>p<span id="ysuwqgo" class="br0">(</span><span id="kwyicia" class="st0">"x"</span><span id="wquwyew" class="br0">)</span><span id="mgqceeu" class="br0">)</span><span id="myceayo" class="co1">-- 1</span><span id="iuwikay" class="kw1">print</span><span id="yamysqo" class="br0">(</span>p<span id="oicwqou" class="br0">(</span><span id="quwiuaa" class="st0">"y"</span><span id="umgauuc" class="br0">)</span><span id="mgaceuk" class="br0">)</span><span id="auyceca" class="co1">-- 2 </span>  (tng)</pre><br /><br />x,y 实际被存攑֜ closure 里,每次调用 function point 都有一份独立的 closure。当?dng)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 Ӟ需要掂量一下了(jin)。这臛_包含一个再 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 上的一文章讨Z(jin)q个问题</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="ikmgiyg" class="kw1">function</span> inherit<span id="isugsqo" class="br0">(</span>sub,super<span id="osmgqye" class="br0">)</span><span id="wiceoec" class="kw1">setmetatable</span><span id="yaeycua" class="br0">(</span>sub, <span id="wyswqom" class="br0">{</span> __index=<span id="seycmui" class="kw1">function</span><span id="wgikouk" class="br0">(</span>t,k<span id="soceoem" class="br0">)</span><span id="eauoqgw" class="kw1">local</span> ret=super<span id="wyacgem" class="br0">[</span>k<span id="wakwqgw" class="br0">]</span> sub<span id="myicywm" class="br0">[</span>k<span id="aaugsyo" class="br0">]</span>=ret <span id="ikmgagg" class="kw1">return</span> ret <span id="ymgykqo" class="kw1">end</span><span id="keqseci" class="br0">}</span><span id="ueykwkk" class="br0">)</span><span id="suwisqg" 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="sewysaq" class="kw1">function</span> foo<span id="soyimss" class="br0">(</span>arg<span id="amgcuce" class="br0">)</span> arg=arg <span id="augykqg" class="kw1">or</span><span id="qciswss" class="st0">"default"</span> ... <span id="oykeguk" class="kw1">end</span></pre><br />利用 or q算赋缺省值是最常用的技巧。上例中Q如?arg ?nil Qarg ׃(x)被赋gؓ(f) "default" 。但是这个技巧有个缺P当缺省值是 true 的时候会(x)有点问题?br /><pre class="code">a=a <span id="uoacwuc" class="kw1">or</span><span id="eyswomk" class="kw1">true</span><span id="auoqsiq" class="co1">-- 错误的写法,?a 明确写ؓ(f) false 的时候,也会(x)被改变成 true ?/span> a= a ~= <span id="myiuoec" class="kw1">false</span><span id="myscecc" class="co1">-- 正确的写法,?a ?nil 的时候,被赋gؓ(f) true Q?false 则不变?</span>  (tng)</pre><br /><br />另外Qy妙?and or q可以实现类?C 语言中的 ?: 三元操作Q?br /><pre class="code"><span id="soimgwm" class="kw1">function</span><span id="wkeyayo" class="kw1">max</span><span id="wasoyww" class="br0">(</span>a,b<span id="qkeissa" class="br0">)</span><span id="mykuowc" class="kw1">return</span> a>b <span id="kwismck" class="kw1">and</span> a <span id="wimeaqg" class="kw1">or</span> b <span id="wykmqow" 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>【{贴】通过例子学习(fn)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在学习(fn)Lua, 所以写出心(j)得和大家׃n, 争取一天写一? 嘿嘿.
  才开始学所以内容很? 希望大家包涵.
  Lua是一U完全免费的脚本语言, 可以和C/C++语言紧密l合,
  它的官方|站在http://www.lua.org. 在网站上可以下蝲到l(f)ua的源? 没有?br />  执行版本, 不过不用担心(j), 因ؓ(f)lua源码可以在Q何一UC/C++的编译器上编?
  
  如果要学?fn)Lua, 官方|站上的Reference是必备的Q上面有每个命o(h)的用法,非常详细?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(h)卛_,
  tar -zxvf lua-5.0.2.tar.gz
  cd lua-5.0.2
  sh ./configure
  make
  q样O(jin)K?jin)?br />  Z(jin)以后使用方便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(jin)调试方便Q采用第二种方式Q执行命?lua e01.lua
  
  输出l果应该是:(x)
  Hello World.
  
4.E序说明
  W一?-- Hello World in Lua
  q句是注释,其中--和C++中的//意思是一L(fng)
  W二?print("Hello World.")
  调用lua内部命o(h)printQ输?Hello World."字符串到屏幕QLua中的字符串全部是?括v来的?br />  q个命o(h)是一个函数的调用Qprint是lua的一个函敎ͼ?Hello World."是print的参数?br />  
5.试试?/b>
  在Lua中有不少字符串的处理操作Q本ơ的译֐试试看的内容是Q找?gu)接两个字W串的操作,
  q且print出来?

?程控制

1. 函数的?br />  以下E序演示?jin)如何在Lua中用函? ?qing)局部变?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可以了(jin).
  本例函数的作用是已知直角三角形直角边, 求斜辚w? 参数a,b分别表示直角辚w,
  在函数内定义?jin)local形变量用于存储斜边的qx(chng). 与C语言相同, 定义在函数内的代
  码不?x)被直接执? 只有ȝ序调用时才会(x)被执?
  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里偶们用到?jin)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不知道你们{对?jin)没有?br />  虽然q里i是一个整型量QLua在处理的时候会(x)自动转成字符串型Q不需偶们费心(j)?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,
  哪怕用?jin)多个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中除?jin)for循环以外, q支持多U@? L(fng)while...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序说明
  首先定义?jin)一个table myData={}, 然后用数字作Z标赋?jin)两个值给? q种
  定义Ҏ(gu)cM于C中的数组, 但与数组不同的是, 每个数组元素不需要ؓ(f)相同cd,
  像本例中一个ؓ(f)整型, 一个ؓ(f)字符?
  
  E序W二部分, 以字W串做ؓ(f)下标, 又向table内增加了(jin)一个元? q种table非常
  像STL里面的map. table下标可以为Lua所支持的Q意基本类? 除了(jin)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? 因ؓ(f)没有指向table的变量了(jin), 所以Lua?x)自动释放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, 定义在了(jin)大table之内, table?br />  table名省略了(jin).
  最后一行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参数的数量不定.
  * 参数会(x)自动存储C个叫arg的table?
  * arg.n中存攑֏数的个数. arg[]加下标就可以遍历所有的参数.
  
  
  2.以table做ؓ(f)参数
  例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句参数没加圆括? 因ؓ(f)以单个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成ؓ(f)一U类似XML的数据描q语a
  * e09中contact{...}, 是一U函数的调用Ҏ(gu), 不要弄؜?br />  * [[...]]是表C多行字W串的方?br />  * 当用C API时此U方式的优势更明? 其中contact{..}部分可以另外存成一配置文g
  
  4.试试?/b>
  x(chng)看哪些地方可以用Ce09中提到的配置Ҏ(gu)呢?
  

?Lua与C的交?/strong>

 1.?/b>
  
  Lua与C/C++l合是很紧密? Lua与C++交互是徏立在Lua与C的基上的, 所
  以偶先从Lua与C讲v.
  
  正如W一讲所? q行LuaE序或者说调用Lua主要有两U方?
  * 通过命o(h)行执?Lua"命o(h)
  * 通过Lua的C?br />  虽然此前偶们一直用W一U方? 但偶要告诉你, 通过Lua的C库执行才是游戏中
  常用的方?
  
  2.Lua的C?/b>
  
  Lua的C库可以做为Shared Library调用, 但一般开发游戏时?x)把Lua的所有源E序
  都包含在? q不把Lua~译成共享库的Ş? 因ؓ(f)LuaE序只有100多K, 而且几乎
  可以在Q何编译器下Clean Compile. 带Lua源程序的另一个好处时, 可以随时对Lua
  本nq行扩充, 增加偶们所需的功?
  
  Lua的C库提供一pdAPI:
  * 理全局变量
  * 理tables
  * 调用函数
  * 定义新函? q也可以完全由C实现
  * 垃圾攉器Garbage collector, 虽然Lua可以自动q行, 但往往不是立即执行?
   所以对实时性要求比较高的程? ?x)自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都?x)被解释成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都?x)被解释成Luaq执?
  与上例不同的? 本例调用?jin)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源码?wi)一L(fng)?br />
?C/C++中用Lua函数

1.?br />  偶们q次主要说说怎么由Lua定义函数, 然后在C或者C++中调? q里偶们
  暂不涉及(qing)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. 因ؓ(f)偶们
  q个E序里只定义?jin)一个add()函数, 所以程序执行后q不直接l果, 效果相当
  于在C中定义了(jin)一个函C?
  
  Lua的函数可以有多个参数, 也可以有多个q回? q都是由?stack)实现?
  需要调用一个函数时, 把q个函数压入? 然后序压入所有参? 然后?br />  lua_call()调用q个函数. 函数q回? q回g是存攑֜栈中. q个q程?br />  汇编执行函数调用的过E是一L(fng).
  
  例e13.cpp 是一个调用上面的Lua函数的例?br />  #include
  
  extern "C" { // q是个C++E序, 所以要extern "C",
     // 因ؓ(f)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了(jin), 所以这ơ只说说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.全局变量
  上面偶们用到?jin)lua_getglobal()但ƈ没有详细? q里偶们再D两个例子来说下全局变量
  lua_getglobal()的作用就是把lua中全局变量的值压入栈
  lua_getglobal(L, "z");
  z = (int)lua_tonumber(L, 1);
  lua_pop(L, 1);
  假设LuaE序中定义了(jin)一个全局变量z, q段程序就是把z的值取出放入C的变量z?
  
  另外Lua中还有一个对应的函数l(f)ua_setglobal(), 作用是用栈顶的值填充指定的全局变量
  lua_pushnumber(L, 10);
  lua_setglobal(L, "z");
  例如q段程序就是把lua中的全局变量z设ؓ(f)10, 如果lua中未定义z的话, ׃(x)自动创徏一?br />  全局变量zq设?0.
  
  4.试试?/b>
  自己写个函数用C/C++来调用下试试

?调用C/C++函数

1.前言
  上次偶说CC/C++中调用Lua的函? 然后有朋友问从Lua中如何调用C/C++?br />  函数, 所以偶们这ơ就来说说这个问? 首先偶们?x)在C++中徏立一个函? 然后
  告知Lua有这个函? 最后再执行? 另外, ׃函数不是在Lua中定义的, 所?br />  无法定函数的正? 可能在调用过E中?x)出? 因此偶们q(sh)(x)说说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(fng),
   所以栈元素的序号也相当于栈中的元素个? 在这? 栈中元素的个数就
   是传入的参数个数.
  * for循环计算所有传入参数的d. q里用到?jin)数D{换lua_tonumber().
  * 然后偶们用lua_pushnumber()把^均值和dpush到栈?
  * 最? 偶们q回2, 表示有两个返回?
  * 偶们虽然在C++中定义了(jin)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了(jin), Ҏ(gu)相同.
  e15.lua执行的方法只能用上例中的C++中执? 而不能用命o(h)行方式执?
  
  3.错误处理
  在上例中, 偶们没有对传入的参数是否为数字进行检? q样做不? 所以这里偶
  们再加上错误处理的片?
  
  把这D加在for循环之内:
  if (!lua_isnumber(L, i)) {
  lua_pushstring(L, "Incorrect argument to 'average'");
  lua_error(L);
  }
  q段的作用就是检传入的是否为数?
  
  加上q段之后, 偶们debug的时候就?x)简单许? 对于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作者:(x) 沐枫 Q第二h生成员)(j)
版权所有{载请注明原出?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,而且它的语法又比较简单明?jin)。不q,使用LuaAPILua引擎集成到程序中Q确实有一些不方便——用落木随风|友的话来说Q就?p用汇~?。当?dng)现在你不用再q么辛苦?jin),因?f)你可以用LuaWrapper For C++。用这个工P在C++中集成Lua脚本是轻而易丄事。你原有的C++函数和类Q几乎不需要Q何改变,可以与Lua脚本׃n?br />  我们接下来,用实例来说明Q如何用LuaWrapper来集成Lua脚本C的程序中厅R?br />
1. (tng) (tng)创徏Lua引擎
  LuaWrap lua; 或?LuaWrap* lua = new LuaWrap;
  创徏一个LuaWrap对象Q就是创Z个Lua脚本引擎。ƈ且根据Lua的特性,你可以创ZQ意多个Lua引擎Q甚臛_以分布在不同的线E当中?br />
2. (tng) (tng)装蝲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. (tng) (tng)获取和设|Lua变量
  能够获取和设|脚本变量的内容Q是一个最基本的功能。你可以使用GetGlobal和SetGlobal函数来做到这一点:(x)
  (1) (tng) (tng)获取变量Q?br />    int a = lua.GetGlobal<int>("a");
    LuaTable table = lua.GetGlobal<LuaTable>("t");
    q里Q?lt;> 里头的类型,是惌的变量的cd?br />  (2) (tng) (tng)讄变量Q?br />    lua.SetGlobal("a", a);
    lua.SetGlobal("t", table);

4. (tng) (tng)调用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. (tng) (tng)如何让Lua也能调用C++的函?br />  _N的地Ҏ(gu)?jin)。假如有下面q样的一个函敎ͼ(x)
  int add(int a, int b)
  {
    return a + b;
  }
  如果惌它能够让Lua使用Q只需它注册到Lua引擎当中可以了(jin)Q?br />  lua.RegisterFunc("add", int(int,int), add);
  q样QLua中就可以用直接用了(jin)Q?br />  QLua脚本Qsum = add(1, 3)

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

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

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

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

  q样注册以后Q我们在Lua中就可以使用q个cM(jin)Q?br />  a = array.new() (tng) (tng)-- 创徏对象Q相当于 a = new Myarray
  a[1] = 10 (tng) (tng)-- 调用__newindexQ也是C++中的 a->setvalue(1, 10)
  a[2] = 20 (tng) (tng)-- 调用__newindexQ也是C++中的 a->setvalue(2, 20)
  print(
    a, (tng) (tng)-- 调用 __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) (tng) (tng)-- 清除对象Q相当于 delete a
  a = nil (tng) (tng)-- 清空 aQ很象C++中的 a = NULL

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

  (3) (tng) (tng)BEGIN_REGLUALIB_MEMBER() …END_REGLUALIB_MEMBER()
    在此处,你可以定义对象的成员函数Q也可以重蝲对象的操作符——是的,pC++的operator重蝲。例如:(x)
    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会(x)试a<=b 转换?not (b < a) )

    __gcQ在垃圾回收时调用此函数Q相当于C++的析构函数。强烈徏议定义此操作W,以免造成内存泄漏{情c(din)比如:(x)
    LUALIB_ITEM_DESTROY("__gc", MyArray )  (tng) (tng)// 垃圾攉时消除对象用?br />
    (? q里要说明一下,在lua中,讉K索引操作W是__indexQ不是__getindexQ在luaWrapper库中Qؓ(f)?jin)方便用,其映射为__getindexQ同Ӟ对__index的定义将?x)被忽略?br />
    p么简单。假如你已经有现成的c,而你没有修改该类的权力,如何其加入到Lua中呢Q答案就是,l承它,把zcd入到Lua中?br />
l束?br />  LuaWrapper 需要用到boost库的支持Qboost/type_traits.hpp, boost/function.hpp, boost/bind.hppQ它使用?jin)C++的模杉K份特化,因此QC++~译器如果不支持此特性,无法编译。目前支持此Ҏ(gu)的~译器已l有很多。在VisualStudo产品pd中,只有VC7.1能支持此Ҏ(gu),因此Q?zhn)如果正在使用VisualStudioQ请认你用的是VisualStudio2003?br />  如果你觉?LuaWrapper For C++ 能够帮助你,我会(x)感觉很荣q。我很愿意将q个E序库分享给大家。顺便一提的是,如果你在使用q程中发现BUGQ或是有好的Q希望?zhn)能与我联pR你在用过E中Q请不要删除文g中的|名信息Q如果你修改?jin)程序库Q请(zhn)在修改的文件中加入(zhn)的修改说明。当?dng)我?x)非常Ƣ迎(zhn)能修改后的程序回馈给我。我?x)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的最大用途是在宿ȝ序中作ؓ(f)脚本使用的?br />  Lua 的语法比较简单,学习(fn)h也比较省力,但功能却q不弱?br />  在Lua中,一切都是变量,除了(jin)关键字。请Cq句话?br />
I. (tng) (tng)首先是注?br />  写一个程序,L不?jin)注释的?br />  在Lua中,你可以用单行注释和多行注释?br />  单行注释中,q箋两个减号"--"表示注释的开始,一直gl到行末为止。相当于C++语言中的"http://"?br />  多行注释中,?--[["表示注释开始,q且一直gl到"]]"为止。这U注释相当于C语言中的"/*?/"。在注释当中Q?[["?]]"是可以嵌套的?br />II. (tng) (tng)Lua~程
  l典?Hello world"的程序L被用来开始介l一U语a。在Lua中,写一个这L(fng)E序很简单:(x)
  print("Hello world")
  在Lua中,语句之间可以用分?Q?隔开Q也可以用空白隔开。一般来_(d)如果多个语句写在同一行的话,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循环?x)?作ؓ(f)步进倹{?br />  你可以用break来中止一个@环?br />  如果你有E序设计的基Q比如你学过BasicQC之类的,你会(x)觉得Lua也不难。但Lua有几个地Ҏ(gu)明显不同于这些程序设计语a的,所以请特别注意?br />
  Q语句块
    语句块在C++中是?{"?}"括v来的Q在Lua中,它是用do ?end 括v来的。比如:(x)
    do print("Hello") end
    你可以在 函数 中和 语句?中定局部变量?br />
  Q赋D?br />    赋D句在Lua被强化了(jin)。它可以同时l多个变量赋倹{?br />    例如Q?br />    a,b,c,d=1,2,3,4
    甚至是:(x)
    a,b=b,a (tng) (tng)-- 多么方便的交换变量功能啊?br />    在默认情况下Q变量L认ؓ(f)是全局的。假如你要定义局部变量,则在W一ơ赋值的时候,需要用local说明。比如:(x)
    local a,b,c = 1,2,3 (tng) (tng)-- a,b,c都是局部变?br />
  Q数D?br />    和C语言一P支持 +, -, *, /。但Luaq多?jin)一?^"。这表示指数乘方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个变量引用的是同一个数据。比如:(x)
    a={1,2}
    b=a
    print(a==b, a~=b) (tng) (tng)-- true, false
    a={1,2}
    b={1,2}
    print(a==b, a~=b) (tng) (tng)-- false, true

  Q逻辑q算
    and, or, not
    其中Qand ?or 与C语言区别特别大?br />    在这里,请先CQ在Lua中,只有false和nil才计ؓ(f)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

    丑և个例子:(x)
     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它相当于:(x)if not x then x = v end ?br />
  Q运符优先U,从高C序如下Q?br />    ^
    not - Q一元运)(j)
     * /
     + -
     ..Q字W串q接Q?br />     < > <= >= ~= ==
     and
     or

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

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

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

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

    ׃q种字符串只能写在一行中Q因此,不可避免的要用到转义字符。加入了(jin)转义字符的串Q看h实在是不敢恭l_(d)比如Q?br />    "one line\nnext line\n\"in quotes\", 'in quotes'"
    一大堆?\"W号让h看v来很倒胃口。如果你与我有同感,那么Q我们在Lua中,可以用另一U表C方法:(x)?[["?]]"多行的字符串括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如果含有单独用的"[["?]]"׃然得?\["?\]"来避免歧义。当?dng)q种情况是极会(x)发生的?br />
  E. (tng) (tng)Table
    关系表类型,q是一个很强大的类型。我们可以把q个cd看作是一个数l。只是C语言的数l,只能用正整数来作索引Q在Lua中,你可以用Lcd来作数组的烦(ch)引,除了(jin)nil。同P在C语言中,数组的内容只允许一U类型;在Lua中,你也可以用Q意类型的值来作数l的内容Q除?jin)nil?br />    Table的定义很单,它的主要特征是用"{"?}"来括起一pd数据元素的。比如:(x)

    T1 = {} (tng) (tng)-- 定义一个空?br />    T1[1]=10 (tng) (tng)-- 然后我们可以象C语言一h使用它了(jin)?br />    T1["John"]={Age=27, Gender="Male"}
    q一句相当于Q?br />    T1["John"]={} (tng) (tng)-- 必须先定义成一个表Q还记得未定义的变量是nilcd?br />    T1["John"]["Age"]=27
    T1["John"]["Gender"]="Male"
    当表的烦(ch)引是字符串的时候,我们可以写成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么写:(x)

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

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

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

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

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

  G. (tng) (tng)Userdata ?Thread
    q两个类型的话题Q超Z(jin)本文的内容,׃打算l说?jin)?br />
VI. (tng) (tng)l束?br />  p么结束了(jin)吗?当然不是Q接下来Q需要用Lua解释器,来帮助你理解和实践了(jin)。这小文只是帮助你大体?jin)解Lua的语法。如果你有编E基Q相信会(x)很快对Lua上手?jin)?br />  pC语言一PLua提供?jin)相当多的标准函数来增强语言的功能。用这些标准函敎ͼ你可以很方便的操作各U数据类型,q处理输入输出。有兌斚w的信息,你可以参考《Programming in Lua 》一书,你可以在|络上直接观看电(sh)子版Q网址为:(x)http://www.lua.org/pil/index.html
  当然QLua的最强大的功能是能与宿主E序亲蜜无间的合作,因此Q下一文章,我会(x)告诉大家Q如何在你的E序中用Lua语言作ؓ(f)脚本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我作?jin)一个Lua脚本的C++包装Q有许多朋友感兴,q尝试用,我感到受宠若惊。事实上Q我作的包装Q学?fn)的目的比较强,它还是有许多~陷的。ؓ(f)?jin)让朋友们少走弯路,我推荐用LuaPlus作ؓ(f)C++的包装?/p>

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

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

1. 调用Lua脚本

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

2. 与Lua脚本互相调用

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

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

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

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

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

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

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

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

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

需要下载LuaPlusHelperQ请点这里:(x)
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 提供?jin)高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序?x)是什么样子呢QLua 是一U嵌入式脚本语言Q它非常,速度很快Q功能却非常强大。在创徏其他配置文g或资源格式(以及(qing)与之对应的解析器Q之前,请尝试一?Lua?/blockquote>

管诸如 Perl、Python、PHP ?Ruby 之类的解释性编E语a日益?Web 应用E序q泛地采U?—?它们已经长期用来实现自动化系l管理Q?—?但是诸如 C、C++ 之类的编译性编E语a依然是必需的。编译性编E语a的性能是脚本语a所无法企及(qing)的(只有手工调优的汇~程序的性能才能过它)(j)Q有些Y?—?包括操作pȝ和设备驱动程?—?只能使用~译代码来高效地实现。实际上Q当软g和硬仉要进行无~地q接操作ӞE序员本能地׃(x)选择 C ~译器:(x)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。另外,脚本语言通常都还?sh)(x)提供高U编E构造和便利的操作,E序员可以用这些功能来提高生效率和灵zL。另外,使用解释语言来编E的E序员工作的速度更快Q因不需要编译和链接的步骤。C ?qing)其cM语言中的 “编码、编译、链接、运行?周期~减成了(jin)更ؓ(f)紧凑?“编写脚本、运行”?/p>

Lua 新特?/font>

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

  • Lua cd?/b>?Lua 中,值可以有cdQ但是变量的cd都是动态决定的?i>nil、布?yu)(dng)型、数?/i> ?字符?/i> cd的工作方式与我们期望的一栗?
    • Nil 是gؓ(f) nil 的一U特D类型,用来表示没有倹{?
    • 布尔型的值可以是 true ?false 帔R。(Nil 也可以表C?falseQQ何非 nil 的值都表示 true。)(j)
    • Lua 中所有的数字都是双精度的Q不q我们可以非常简便地~写一些代码来实现其他数字cdQ?
    • 字符串是定长字符数组。(因此Q要在一个字W串后面附加上字W,必须对其q行拯。)(j)
  • 表、函?/i> ?i>U程 cd都是引用。每个都可以赋值给一个变量,作ؓ(f)参数传递,或作回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不?x)在创徏时启动;相反Q它是在创徏之后使用 coroutine.resume(t) 启动的,其中 t 是一个线E。每个协同例E都必须使用 coroutine.yield() 偶尔获得其他协同例程的处理器?
  • 赋D句?/b>Lua 允许使用多种赋D句,可以先对表达式进行求|然后再进行赋倹{例如,下面的语句:(x)

    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)
    

    ?x)生?4 7 5 nil nil。如果变量列表的个数大于值列表的个数Q那么多出的变量都被赋gؓ(f) nilQ因此,b 是 nil。如果值的个数多于变量的个敎ͼ那么多出的值部分就?x)简单地丢弃。在 Lua 中,变量名是大小写敏感的Q这可以解释Z?I 的值是 nil?
  • 块(ChunkQ?/b> ?/i> 可以是Q?Lua 语句序列。块可以保存到文件中Q或者保存到 Lua E序中的字符串中。每个块都是作ؓ(f)一个匿名函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种环境中对每种语言的优~点、权重和折(sh)q行评测Qƈ接受所带来的风险?/p>



回页?/font>


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

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

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

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



回页?/font>


开始?Lua

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

如果(zhn)用的?Debian LinuxQ那么可以以用户的n份运行下面的命o(h)来快速安?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对于开发和调试工作来说非常有用。)(j)创徏一个名?factorial.lua 的文Ӟ然后输入下面的代码:(x)

-- 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进行了(jin)介绍。要执行刚才创徏的代码块Q请q行命o(h) 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代器,以及(qing)一l用来处理字W串、生及(qing)攉数据和执行数学计操作的标准库。在 Lua 5.0 Reference Manual 中有?Lua 语言的完整介l(请参?参考资?/font>Q?/p>

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

Lua ?/font>

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

与其他编E语a不同QLua 表的概念不需要是异构的:(x)表可以包含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提供了(jin)很多q代器函数来对表q行处理。全局变量 table 提供?jin)这些函敎ͼ是的QLua 包就是表Q。有些函敎ͼ例如 table.foreachi()Q会(x)期望一个从 1Q数?1Q开始的q箋整数范围Q?/p>
> table.foreachi(t1, print)
1 moustache
2 3

另外一些函敎ͼ例如 table.foreach()Q会(x)Ҏ(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行?jin)优化,但是所有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 是ؓ(f)?jin)嵌入到使用另外一U语aQ例?C ?C++Q编写的宿主应用E序中,q与宿主应用E序协同工作Q因此数据可以在 C 环境?Lua 之间q行׃n。正?Lua 5.0 Reference Manual 所_(d)userdata cd允许我们?Lua 变量中保存(sh)Q意的 C 数据。我们可以认?userdata 是一个字节数l?—?字节可以表示指针、结构或宿主应用E序中的文g?/p>

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

元表

׃表和用户数据都非常灵z,因此 Lua 允许我们重蝲q两U类型的数据的操作(不能重蝲其他 6 U类型)(j)?i>元表 是一个(普通的QLua 表,它将标准操作映射成我们提供的函数。元表的键值称?i>事gQ|换而言之就是函敎ͼ(j)UCؓ(f)元方?/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段代码?x)生下面的文本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)每当表中不存在键值时׃(x)被调用。下面是一个例子,它记?(memoize) 函数的|(x)

-- 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)?x)看到cM?blue black blue 的内宏V?/p>

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

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



回页?/font>


嵌入和扩?/font>

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

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

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

清单 2 l出?jin)一个简单的 C E序Q节选自 参考资?/font> ?Programming in Lua 一书的W?24 章)(j)Q它实现?jin)一个很但却功能完善的 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 行包括了(jin) Lua 的标准函敎ͼ几个在所?Lua 库中都会(x)使用的方便函C?qing)用来打开库的函数。第 9 行创Z(jin)一?Lua 状?/i>。所有的状态最初都是空的;我们可以使用 luaopen_...() 函数库d到状态中Q如W?10 行到W?14 行所C?/p>

W?17 行和 luaL_loadbuffer() ?x)?stdin 中以块的形式接收输入Qƈ对其q行~译Q然后将其放入虚拟堆栈中。第 18 行从堆栈中弹出数据ƈ执行之。如果在执行时出C(jin)错误Q就向堆栈中压入一?Lua 字符丌Ӏ第 20 行访问栈Ӟ栈顶的烦(ch)引ؓ(f) -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代码类|(x)使用 lua_getglobal() 来获得函敎ͼ参数压入堆栈,调用 lua_pcall()Q然后处理结果。如?Lua 函数q回 n 个|那么W一个值的位置在堆栈的 -n 处,最后一个值在堆栈中的位置?-1?/p>

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





回页?/font>


l束?/font>

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

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



回页?/font>


参考资?

学习(fn)

获得产品和技?/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 的首席编辑。他在普渡大学获得了(jin)计算机硕士学位,?1982 q以来,׃直在使用 Pascal、C、Perl、Java 以及(qing)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
  • 官方资源 (tng)
  • LuaC֌ (tng)
  • Lua (tng)文档
    • [Lua架构] - 描述?jin)Lua的业务驱动方式,目的以及(qing)架构解决Ҏ(gu)?/li>
  • 带有例证的Lua文档
  • Lua (tng)教程
  • 认证考试 (tng)
  • Benchmarks
  • 语言比较 (tng)
  • Lua 其他相关站点


  • 李锦?mybios) 2006-11-18 09:35 发表评论
    ]]>
    þֻоƷҳ| þ99Ʒ鶹լլ| þù޸ۿ| þþƷѲ| Ըߺþþþþþþ| ھƷþþþþòӰԺ| þþ| þۺۺϾþ97ɫ| þþƷѿ| 2021ƷۺϾþ| ɫۺϾþþĻ| þþۺϾɫۺ̾| ƷۺϾþþþþ98| һƷþð͹| vaþþþ| Ʒۺþþþþ| þþƷaĻ| ھƷþù½| þAVۺϺɫ| Ʒݾþþþø99| Ʒ91þþþþþa | Ʒ99þþƷ| þúݺһƷۺ| 2021ƷۺϾþ| պһþ | þһѵ | þоƷƵ| ŷþۺϾɫۺ| þۺϾþþ| ھƷþþþӰԺ| ŷ޾ƷþþavӰ| 鶹Ʒþþþþþ99| þþùҺ| ۺϾþҹAV | þþþһƷɫ| þþƷۺ| þþþһ| AƬٸþ| 2019þþø456| ޳ɫWWWþվ| ɫۺϾþʮ·|