﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-&lt;font size=5&gt;李锦俊(mybios)的blog&lt;/font&gt;-随笔分类-LUA</title><link>http://www.cppblog.com/mybios/category/3079.html</link><description>游戏开发 C++ Cocos2d-x OpenGL DirectX 数学 计算机图形学 SQL Server
&lt;BR&gt;
&lt;BR&gt;</description><language>zh-cn</language><lastBuildDate>Tue, 19 Jul 2016 07:15:22 GMT</lastBuildDate><pubDate>Tue, 19 Jul 2016 07:15:22 GMT</pubDate><ttl>60</ttl><item><title>tolua++导出C++类的一些问题和解决方法</title><link>http://www.cppblog.com/mybios/archive/2010/02/09/107616.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Tue, 09 Feb 2010 11:43:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2010/02/09/107616.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/107616.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2010/02/09/107616.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/107616.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/107616.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 我在尝试导出Ogre的所有类接口到lua中使用，参考CEGUI的方法，使用的是tolua++来导出C++类对象。在使用过程中，遇到了一些问题。问题1：表现为tolua++编译错误，错误信息是：***curr code for error is $pfile "OgreBase/OgreVector2.h" 这里我编写了一个OgreBase.pkg文件（给tolua++用来生成导出导入lua的定义文...&nbsp;&nbsp;<a href='http://www.cppblog.com/mybios/archive/2010/02/09/107616.html'>阅读全文</a><img src ="http://www.cppblog.com/mybios/aggbug/107616.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2010-02-09 19:43 <a href="http://www.cppblog.com/mybios/archive/2010/02/09/107616.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【原创】魔兽争霸III 地图编辑器原理（关键是脚本）</title><link>http://www.cppblog.com/mybios/archive/2006/11/19/15404.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 18 Nov 2006 16:20:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/19/15404.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15404.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/19/15404.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15404.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15404.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: <font color="#ff0000">　　注意：本文纯属是本人从研究魔兽争霸III地图编辑器的过程中的一种猜想，所以，不当之处，还请高手指出。谢谢！</font><br><br>　　魔兽争霸III我以前玩得比较多，也听说他的地图编辑器非常牛X，以前也曾经想编辑个地图出来。但是，限于当时得水平问题，没有成功。直到最近在研究如何制作游戏的时候，打开魔兽争霸III的地图编辑器来看，突然有一种扩然开朗的感觉！哦！原来地图编辑器是这样出来的！闲话不多说！马上进入正题！<br><br>　　魔兽争霸III的地图编辑器使用了一个文件来代表一个地图，地图里包含了什么东西？我无从得知，但是，从他的编辑器上看，看到编辑器能对地图修改的东西，就可以大概猜想到有哪些东西。仔细看地图编辑器，看到有那么几个模块：地形编辑器、开关编辑器、声音编辑器、物体编辑器、战役编辑器、AI编辑器、物体管理器、输入管理器。我把我的理解逐一说来<a href="http://www.cppblog.com/mybios/archive/2006/11/19/15404.html">阅读全文</a>&nbsp;&nbsp;<a href='http://www.cppblog.com/mybios/archive/2006/11/19/15404.html'>阅读全文</a><img src ="http://www.cppblog.com/mybios/aggbug/15404.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-19 00:20 <a href="http://www.cppblog.com/mybios/archive/2006/11/19/15404.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】Lua 编程技巧</title><link>http://www.cppblog.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.cppblog.com/mybios/archive/2006/11/18/15358.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15358.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/18/15358.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15358.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15358.html</trackback:ping><description><![CDATA[
		<div class="page">
				<a href="http://blog.codingnow.com/cloud/Lua5">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 href="http://blog.codingnow.com/cloud/Lua5">Lua</a> 初学者最容易犯的错误。global 变量实际上是放在一张全局的 table 里的。global 变量实际上是利用一个 string (变量名作 key) 去访问这个 table 。虽然<a href="http://blog.codingnow.com/2005/10/lua_table.html" target="_blank"><img title="在新窗口中打开" height="11" alt="[InterWiki]" hspace="4" src="http://blog.codingnow.com/cloud//images/inter.gif" width="11" border="0" /></a><a href="http://blog.codingnow.com/2005/10/lua_table.html">Lua5 的 table 效率很高</a> ，但是相对于 local 变量，依然有很大的效率损失。local 变量是直接通过 <a href="http://blog.codingnow.com/cloud/Lua5">Lua</a> 的堆栈访问的。有些 global 变量的访问是不经意的，比如我们有双重循环操作一个迭代的 table：<br /><pre class="code"><span class="kw1">for</span> k1,v1 <span class="kw1">in</span><span class="kw1">pairs</span><span class="br0">(</span>tbl<span class="br0">)</span><span class="kw1">do</span><span class="kw1">for</span> k2,v2 <span class="kw1">in</span><span class="kw1">pairs</span><span class="br0">(</span>v1<span class="br0">)</span><span class="kw1">do</span>
        ...	
    <span class="kw1">end</span>
end</pre><br /><br />这里，pairs 其实是一个全局变量应用的函数。如果我们这样做：<br /><pre class="code"><span class="kw1">do</span><span class="kw1">local</span><span class="kw1">pairs</span>=pairs
    <span class="kw1">for</span> k1,v1 <span class="kw1">in</span><span class="kw1">pairs</span><span class="br0">(</span>tbl<span class="br0">)</span><span class="kw1">do</span><span class="kw1">for</span> k2,v2 <span class="kw1">in</span><span class="kw1">pairs</span><span class="br0">(</span>v1<span class="br0">)</span><span class="kw1">do</span>
            ...	
        <span class="kw1">end</span><span class="kw1">end</span>
end</pre><br /><br />效率会稍微提高一些。如果是单层循环，这样做就没有意义。因为 for ... in 循环中的 pairs 这个函数只会被调用一次，而不是每次循环都去调。我们的原则其实是，被多次读取的 global 变量，都应该提取出来放到 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> 字符串的连接操作，会产生新的对象。这是由 lua 本身的 string 管理机制导致的。lua 在 VM 内对相同的 string 永远只保留一份唯一 copy ，这样，所有字符串比较就可以简化为地址比较。这也是 lua 的 table 工作很快的原因之一。这种 string 管理的策略，跟 java 等一样，所以跟 java 一样，应该尽量避免在循环内不断的连接字符串，比如 a = a..x 这样。每次运行，都很可能会生成一份新的 copy 。<br /><br />同样，记住，每次构造一份 table 都会多一份 table 的 copy 。比如在 lua 里，把平面坐标封装成 { x, y } 用于参数传递，就需要考虑这个问题。每次你想构造一个坐标对象传递给一个函数，{ 10,20 }  这样明确的写出，都会构造一个新的 table 出来。要么，我们想办法考虑 table 的重用；要么，干脆用 x,y 两个参数传递坐标。<br /><br />同样需要注意的是以 function foo (...) 这种方式定义函数， ... 这种不定参数，每次调用的时候都会被定义出一个 table 存放不定数量的参数。<br /><br />这些临时构造的对象往往要到 gc 的时候才被回收，过于频繁的 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 } 这样封装一个坐标。不过还有一个方法可供选择。它稍微轻量一点。<br /><br /><pre class="code"><span class="kw1">function</span> point <span class="br0">(</span>x,y<span class="br0">)</span><span class="kw1">return</span><span class="kw1">function</span><span class="br0">(</span><span class="br0">)</span><span class="kw1">return</span> x,y <span class="kw1">end</span>
end
 
<span class="co1">-- 使用范例</span>
p=point<span class="br0">(</span><span class="nu0">1</span>,<span class="nu0">2</span><span class="br0">)</span><span class="kw1">print</span><span class="br0">(</span>p<span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="co1">-- 输出 1	 2 </span>
 </pre><br /><br />如果你愿意，还可以做的复杂一点：<br /><pre class="code"><span class="kw1">function</span> point <span class="br0">(</span>x,y<span class="br0">)</span><span class="kw1">return</span><span class="kw1">function</span><span class="br0">(</span>idx<span class="br0">)</span><span class="kw1">if</span> idx==<span class="st0">"x"</span><span class="kw1">then</span><span class="kw1">return</span> x
		<span class="kw1">elseif</span> idx==<span class="st0">"y"</span><span class="kw1">then</span><span class="kw1">return</span> y
		<span class="kw1">else</span><span class="kw1">return</span> x,y <span class="kw1">end</span><span class="kw1">end</span>
end
 
<span class="co1">-- 使用范例</span>
p=point<span class="br0">(</span><span class="nu0">1</span>,<span class="nu0">2</span><span class="br0">)</span><span class="kw1">print</span><span class="br0">(</span>p<span class="br0">(</span><span class="st0">"x"</span><span class="br0">)</span><span class="br0">)</span><span class="co1">-- 1</span><span class="kw1">print</span><span class="br0">(</span>p<span class="br0">(</span><span class="st0">"y"</span><span class="br0">)</span><span class="br0">)</span><span 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 传递字符串</strong> 字符串常量在 Lua VM 内部工作的非常快，但是一个从 C 向 lua vm 通过 lua_pushstring 之类的 api 传递进 VM 时，就需要掂量一下了。这至少包含一个再 hash 和匹配的过程。<a href="http://blog.codingnow.com/2006/01/_lua.html" target="_blank"><img title="在新窗口中打开" height="11" alt="[InterWiki]" hspace="4" src="http://blog.codingnow.com/cloud//images/inter.gif" width="11" border="0" /></a><a href="http://blog.codingnow.com/2006/01/_lua.html">我的 Blog 上的一篇文章讨论了这个问题</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 中的继承</strong> lua 中实现 OO ，虚表往往设置一个 metatable 并设置 __index ，而继承则用 metatable 的 __index 把虚表串起来。当类继承层次过多的时候，效率比较低，那么就可以用下面这个技巧。<br /><pre class="code"><span class="kw1">function</span> inherit<span class="br0">(</span>sub,super<span class="br0">)</span><span class="kw1">setmetatable</span><span class="br0">(</span>sub,
     <span class="br0">{</span> __index=<span class="kw1">function</span><span class="br0">(</span>t,k<span class="br0">)</span><span class="kw1">local</span> ret=super<span class="br0">[</span>k<span class="br0">]</span>
             sub<span class="br0">[</span>k<span class="br0">]</span>=ret
             <span class="kw1">return</span> ret
     <span class="kw1">end</span><span class="br0">}</span><span class="br0">)</span><span 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>利用逻辑运算的短路效应</strong> lua 编程中，and or 跟 C 一样是有短路效应的，不过他们的返回值并非 bool 类型，而是表达式中的左值或者右值。我们常常利用这个特性来简化代码。<br /><pre class="code"><span class="kw1">function</span> foo<span class="br0">(</span>arg<span class="br0">)</span>
     arg=arg <span class="kw1">or</span><span class="st0">"default"</span>
     ...
<span class="kw1">end</span></pre><br />利用 or 运算赋缺省值是最常用的技巧。上例中，如果 arg 为 nil ，arg 就会被赋值为 "default" 。但是这个技巧有个缺陷，当缺省值是 true 的时候会有点问题。<br /><pre class="code">a=a <span class="kw1">or</span><span class="kw1">true</span><span class="co1">-- 错误的写法，当 a 明确写为 false 的时候，也会被改变成 true 。</span>
a= a ~= <span class="kw1">false</span><span class="co1">-- 正确的写法，当 a 为 nil 的时候，被赋值为 true ；而 false 则不变。 </span>
 </pre><br /><br />另外，巧妙使用 and or 还可以实现类似 C 语言中的 ?: 三元操作：<br /><pre class="code"><span class="kw1">function</span><span class="kw1">max</span><span class="br0">(</span>a,b<span class="br0">)</span><span class="kw1">return</span> a&gt;b <span class="kw1">and</span> a <span class="kw1">or</span> b
<span class="kw1">end</span></pre><br />上面这个函数可以返回 a 和 b 中较大的一个，其逻辑类似 C 语言中的 return (a&gt;b) ? a : b ;</div>
<img src ="http://www.cppblog.com/mybios/aggbug/15358.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-18 15:04 <a href="http://www.cppblog.com/mybios/archive/2006/11/18/15358.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】通过例子学习Lua</title><link>http://www.cppblog.com/mybios/archive/2006/11/18/15356.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 18 Nov 2006 06:34:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/18/15356.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15356.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/18/15356.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15356.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15356.html</trackback:ping><description><![CDATA[
		<strong>
				<font size="6">一.Hello World</font>
				<br />
				<br />1.前言<br /></strong>　　<br />　　偶最近在学习Lua, 所以写出心得和大家共享, 争取一天写一篇, 嘿嘿.<br />　　才开始学所以内容很浅, 希望大家包涵.<br />　　Lua是一种完全免费的脚本语言, 可以和C/C++语言紧密结合,<br />　　它的官方网站在http://www.lua.org. 在网站上可以下载到lua的源码, 没有可<br />　　执行版本, 不过不用担心, 因为lua源码可以在任何一种C/C++的编译器上编译.<br />　　<br />　　如果要学习Lua, 官方网站上的Reference是必备的，上面有每个命令的用法，非常详细。<br />　　参考手册 http://www.lua.org/manual/5.0/<br />　　作者写的Programming in Lua http://www.lua.org/pil/<br />　　<br /><b>2.编译</b><br />　　如果用的VC6, 可以下载所需的project文件,地址在<br />　　http://sourceforge.net/project/showfiles.php?group_id=32250&amp;package_id=115604<br />　　VSNET2003可以下载这个sln文件http://home.comcast.net/~vertigrated/lua/vs7.zip<br />　　偶用的是cygwin和linux, 打入以下命令即可,<br />　　tar -zxvf lua-5.0.2.tar.gz<br />　　cd lua-5.0.2<br />　　sh ./configure<br />　　make<br />　　这样就OK了。<br />　　为了以后使用方便，最好把bin目录加入到path里面。<br />　　<br /><b>3."Hello, world!"</b><br />　　现在开始偶们的第一个小程序"Hello, world!"<br />　　把以下程序打入文件e01.lua<br />　　<br />　　例1:e01.lua<br />　　-- Hello World in Lua<br />　　print("Hello World.")<br />　　<br />　　Lua有两种执行方式，一种是嵌入到C程序中执行，还有一种是直接从命令行方式下执行。<br />　　这里为了调试方便，采用第二种方式，执行命令 lua e01.lua<br />　　<br />　　输出结果应该是：<br />　　Hello World.<br />　　<br /><b>4.程序说明</b><br />　　第一行 -- Hello World in Lua<br />　　这句是注释，其中--和C++中的//意思是一样的<br />　　第二行 print("Hello World.")<br />　　调用lua内部命令print，输出"Hello World."字符串到屏幕，Lua中的字符串全部是由"括起来的。<br />　　这个命令是一个函数的调用，print是lua的一个函数，而"Hello World."是print的参数。<br />　　<br /><b>5.试试看</b><br />　　在Lua中有不少字符串的处理操作，本次的课后试试看的内容就是，找出连接两个字符串的操作，<br />　　并且print出来。 <br /><br /><font size="6"><strong>二.流程控制</strong></font><br /><br /><strong>1. 函数的使用<br /></strong>　　以下程序演示了如何在Lua中使用函数, 及局部变量<br />　　例e02.lua<br />　　-- functions<br />　　function pythagorean(a, b)<br />　　local c2 = a^2 + b^2<br />　　return sqrt(c2)<br />　　end<br />　　print(pythagorean(3,4))<br />　　<br />　　运行结果<br />　　5<br />　　<br />　　程序说明<br />　　在Lua中函数的定义格式为:<br />　　function 函数名(参数)<br />　　...<br />　　end<br />　　与Pascal语言不同, end不需要与begin配对, 只需要在函数结束后打个end就可以了.<br />　　本例函数的作用是已知直角三角形直角边, 求斜边长度. 参数a,b分别表示直角边长,<br />　　在函数内定义了local形变量用于存储斜边的平方. 与C语言相同, 定义在函数内的代<br />　　码不会被直接执行, 只有主程序调用时才会被执行.<br />　　local表示定义一个局部变量, 如果不加local刚表示c2为一个全局变量, local的作用域<br />　　是在最里层的end和其配对的关键字之间, 如if ... end, while ... end等。全局变量的<br />　　作用域是整个程序。<br />　　<br />　　<b>2. 循环语句</b><br />　　例e03.lua<br />　　-- Loops<br />　　for i=1,5 do<br />　　print("i is now " .. i)<br />　　end<br />　　<br />　　运行结果<br />　　i is now 1<br />　　i is now 2<br />　　i is now 3<br />　　i is now 4<br />　　i is now 5<br />　　<br />　　程序说明<br />　　这里偶们用到了for语句<br />　　for 变量 = 参数1, 参数2, 参数3 do<br />　　循环体<br />　　end<br />　　变量将以参数3为步长, 由参数1变化到参数2<br />　　例如:<br />　　for i=1,f(x) do print(i) end<br />　　for i=10,1,-1 do print(i) end<br />　　<br />　　这里print("i is now " .. i)中，偶们用到了..，这是用来连接两个字符串的，<br />　　偶在(1)的试试看中提到的，不知道你们答对了没有。<br />　　虽然这里i是一个整型量，Lua在处理的时候会自动转成字符串型，不需偶们费心。<br />　　<br />　　<b>3. 条件分支语句</b><br />　　例e04.lua<br />　　-- Loops and conditionals<br />　　for i=1,5 do<br />　　print(“i is now “ .. i)<br />　　　　　if i &lt; 2 then<br />　　　　　print(“small”)<br />　　　　　elseif i &lt; 4 then<br />　　　　　print(“medium”)<br />　　　　　else<br />　　　　　print(“big”)<br />　　　　　end<br />　　end<br />　　<br />　　运行结果<br />　　i is now 1<br />　　small<br />　　i is now 2<br />　　medium<br />　　i is now 3<br />　　medium<br />　　i is now 4<br />　　big<br />　　i is now 5<br />　　big<br />　　<br />　　程序说明<br />　　if else用法比较简单, 类似于C语言, 不过此处需要注意的是整个if只需要一个end,<br />　　哪怕用了多个elseif, 也是一个end.<br />　　例如<br />　　　　if op == "+" then<br />　　　　　r = a + b<br />　　　　elseif op == "-" then<br />　　　　　r = a - b<br />　　　　elseif op == "*" then<br />　　　　　r = a*b<br />　　　　elseif op == "/" then<br />　　　　　r = a/b<br />　　　　else<br />　　　　　error("invalid operation")<br />　　　　end<br />　　<br />　　<br />　　<b>4.试试看</b><br />　　Lua中除了for循环以外, 还支持多种循环, 请用while...do和repeat...until改写本文中的for程序 <br /><br /><font size="6"><strong>三.Lua数据结构</strong></font><br /><br />　<b>1.简介</b><br />　　Lua语言只有一种基本数据结构, 那就是table, 所有其他数据结构如数组啦,<br />　　类啦, 都可以由table实现.<br />　　例e05.lua<br />　　-- Arrays<br />　　myData = {}<br />　　myData[0] = “foo”<br />　　myData[1] = 42<br />　　<br />　　-- Hash tables<br />　　myData[“bar”] = “baz”<br />　　<br />　　-- Iterate through the<br />　　-- structure<br />　　for key, value in myData do<br />　　print(key .. “=“ .. value)<br />　　end<br />　　<br />　　输出结果<br />　　0=foo<br />　　1=42<br />　　bar=baz<br />　　<br />　　程序说明<br />　　首先定义了一个table myData={}, 然后用数字作为下标赋了两个值给它. 这种<br />　　定义方法类似于C中的数组, 但与数组不同的是, 每个数组元素不需要为相同类型,<br />　　就像本例中一个为整型, 一个为字符串.<br />　　<br />　　程序第二部分, 以字符串做为下标, 又向table内增加了一个元素. 这种table非常<br />　　像STL里面的map. table下标可以为Lua所支持的任意基本类型, 除了nil值以外.<br />　　<br />　　Lua对Table占用内存的处理是自动的, 如下面这段代码<br />　　　　a = {}<br />　　　　a["x"] = 10<br />　　　　b = a　　　-- `b' refers to the same table as `a'<br />　　　　print(b["x"])　--&gt; 10<br />　　　　b["x"] = 20<br />　　　　print(a["x"])　--&gt; 20<br />　　　　a = nil　　-- now only `b' still refers to the table<br />　　　　b = nil　　-- now there are no references left to the table<br />　　b和a都指向相同的table, 只占用一块内存, 当执行到a = nil时, b仍然指向table,<br />　　而当执行到b=nil时, 因为没有指向table的变量了, 所以Lua会自动释放table所占内存<br />　　<br />　　<b>3.Table的嵌套</b><br />　　Table的使用还可以嵌套，如下例<br />　　例e06.lua<br />　　-- Table ‘constructor’<br />　　myPolygon = {<br />　　color=“blue”,<br />　　thickness=2,<br />　　npoints=4;<br />　　{x=0,　 y=0},<br />　　{x=-10, y=0},<br />　　{x=-5,　y=4},<br />　　{x=0,　 y=4}<br />　　}<br />　　<br />　　-- Print the color<br />　　print(myPolygon[“color”])<br />　　<br />　　-- Print it again using dot<br />　　-- notation<br />　　print(myPolygon.color)<br />　　<br />　　-- The points are accessible<br />　　-- in myPolygon[1] to myPolygon[4]<br />　　<br />　　-- Print the second point’s x<br />　　-- coordinate<br />　　print(myPolygon[2].x)<br />　　<br />　　<b>程序说明</b><br />　　首先建立一个table, 与上一例不同的是，在table的constructor里面有{x=0,y=0},<br />　　这是什么意思呢？ 这其实就是一个小table, 定义在了大table之内, 小table的<br />　　table名省略了.<br />　　最后一行myPolygon[2].x，就是大table里面小table的访问方式.<br />　　 <br /><strong><font size="6">四.函数的调用</font></strong><br /><br />　<b>1.不定参数</b><br />　　例e07.lua<br />　　-- Functions can take a<br />　　-- variable number of<br />　　-- arguments.<!--DVNEWS_AD_BEGIN--><br />　　function funky_print (...)<br />　　for i=1, arg.n do<br />　　print("FuNkY: " .. arg[i])<br />　　end<br />　　end<br />　　<br />　　funky_print("one", "two")<br />　　<br />　　运行结果<br />　　FuNkY: one<br />　　FuNkY: two<br />　　<br />　　程序说明<br />　　* 如果以...为参数, 则表示参数的数量不定.<br />　　* 参数将会自动存储到一个叫arg的table中.<br />　　* arg.n中存放参数的个数. arg[]加下标就可以遍历所有的参数.<br />　　<br />　　<br />　　<b>2.以table做为参数</b><br />　　例e08.lua<br />　　-- Functions with table<br />　　-- parameters<br />　　function print_contents(t)<br />　　for k,v in t do<br />　　print(k .. "=" .. v)<br />　　end<br />　　end<br />　　print_contents{x=10, y=20}<br />　　<br />　　运行结果<br />　　x=10<br />　　y=20<br />　　<br />　　程序说明<br />　　* print_contents{x=10, y=20}这句参数没加圆括号, 因为以单个table为参数的时候, 不需要加圆括号<br />　　* for k,v in t do 这个语句是对table中的所有值遍历, k中存放名称, v中存放值<br />　　<br />　　<br />　　<b>3.把Lua变成类似XML的数据描述语言</b><br />　　例e09.lua<br />　　function contact(t)<br />　　-- add the contact ‘t’, which is<br />　　-- stored as a table, to a database<br />　　end<br />　　<br />　　contact {<br />　　name = "Game Developer",<br />　　email = "hack@ogdev.net",<br />　　url = "http://www.ogdev.net",<br />　　quote = [[<br />　　There are<br />　　10 types of people<br />　　who can understand binary.]]<br />　　}<br />　　<br />　　contact {<br />　　-- some other contact<br />　　}<br />　　<br />　　程序说明<br />　　* 把function和table结合, 可以使Lua成为一种类似XML的数据描述语言<br />　　* e09中contact{...}, 是一种函数的调用方法, 不要弄混了<br />　　* [[...]]是表示多行字符串的方法<br />　　* 当使用C API时此种方式的优势更明显, 其中contact{..}部分可以另外存成一配置文件<br />　　<br />　　<b>4.试试看</b><br />　　想想看哪些地方可以用到例e09中提到的配置方法呢？<br />　　<br /><br /><font size="6"><strong>五.Lua与C的交互</strong></font><br /><br />　<b>1.简介</b><br />　　<br />　　Lua与C/C++结合是很紧密的, Lua与C++交互是建立在Lua与C的基础上的, 所<br />　　以偶先从Lua与C讲起.<br />　　<br />　　正如第一讲所说, 运行Lua程序或者说调用Lua主要有两种方式:<!--DVNEWS_AD_BEGIN--><br />　　* 通过命令行执行"Lua"命令<br />　　* 通过Lua的C库<br />　　虽然此前偶们一直用第一种方式, 但偶要告诉你, 通过Lua的C库执行才是游戏中<br />　　常用的方式.<br />　　<br />　　<b>2.Lua的C库</b><br />　　<br />　　Lua的C库可以做为Shared Library调用, 但一般开发游戏时会把Lua的所有源程序<br />　　都包含在内, 并不把Lua编译成共享库的形式. 因为Lua程序只有100多K, 而且几乎<br />　　可以在任何编译器下Clean Compile. 带Lua源程序的另一个好处时, 可以随时对Lua<br />　　本身进行扩充, 增加偶们所需的功能.<br />　　<br />　　Lua的C库提供一系列API:<br />　　* 管理全局变量<br />　　* 管理tables<br />　　* 调用函数<br />　　* 定义新函数, 这也可以完全由C实现<br />　　* 垃圾收集器Garbage collector, 虽然Lua可以自动进行, 但往往不是立即执行的,<br />　　　所以对实时性要求比较高的程序, 会自己调用垃圾收集器<br />　　* 载入并执行Lua程序, 这也可以由Lua自身实现<br />　　* 任何Lua可以实现的功能, 都可以通过Lua的C API实现, 这对于优化程序的运行速度<br />　　　有帮助. 经常调用的共用的Lua程序片断可以转成C程序, 以提高效率. 连Lua都是C写的<br />　　　还有什么C不能实现呢?<br />　　<br />　　<b>3.Lua与C集成的例子</b><br />　　例e10.c<br />　　/* A simple Lua interpreter. */<br />　　#include <stdio.h><br />　　#include <lua.h><br />　　int main(int argc, char *argv[]) {<br />　　char line[BUFSIZ];<br />　　lua_State *L = lua_open(0);<br />　　while (fgets(line, sizeof(line), stdin) != 0)<br />　　lua_dostring(L, line);<br />　　lua_close(L);<br />　　return 0;<br />　　}<br />　　<br />　　编译<br />　　Linux/Cygwin<br />　　* 先编译Lua, 并把头文件放入include路径<br />　　* gcc e10.c -llua -llualib -o e10<br />　　<br />　　VC6/VC2003<br />　　* 先编译Lua, 在Option中设置头文件和库文件路径<br />　　* 新建工程,在工程配置中加入附加库lua.lib和lualib.lib<br />　　* 编译成exe<br />　　<br />　　运行结果<br />　　本程序的功能是实现一个Lua解释器, 输入的每行字符都会被解释成Lua并执行.<br />　　<br />　　程序说明<br />　　* #include <lua.h>包含lua头文件, 然后才可以使用API<br />　　* lua_State *L = lua_open(0) 打开一个Lua执行器<br />　　* fgets(line, sizeof(line), stdin) 从标准输入里读入一行<br />　　* lua_dostring(L, line) 执行此行<br />　　* lua_close(L) 关闭Lua执行器<br />　　<br />　　<br />　　例e11.c<br />　　/* Another simple Lua interpreter. */<br />　　#include <stdio.h><br />　　#include <lua.h><br />　　#include <lualib.h><br />　　int main(int argc, char *argv[]) {<br />　　char line[BUFSIZ];<br />　　lua_State *L = lua_open(0);<br />　　lua_baselibopen(L);<br />　　lua_iolibopen(L);<br />　　lua_strlibopen(L);<br />　　lua_mathlibopen(L);<br />　　while (fgets(line, sizeof(line), stdin) != 0)<br />　　lua_dostring(L, line);<br />　　lua_close(L);<br />　　return 0;<br />　　}<br />　　<br />　　运行结果<br />　　本程序的功能是实现一个Lua解释器, 输入的每行字符都会被解释成Lua并执行.<br />　　与上例不同的是, 本例调用了Lua的一些标准库.<br />　　<br />　　程序说明<br />　　* #include <lualib.h>包含Lua的标准库<br />　　* 以下这几行是用来读入Lua的一些库, 这样偶们的Lua程序就可以有更多的功能.<br />　　lua_baselibopen(L);<br />　　lua_iolibopen(L);<br />　　lua_strlibopen(L);<br />　　lua_mathlibopen(L);<br />　　<br />　　<b>4.试试看</b><br />　　把上面两个小例子在你熟悉的编译器中编译执行, 并试试能否与Lua源码树一起编译<br /><br /><strong><font color="#000000" size="6">六.C/C++中用Lua函数<br /></font></strong><br /><strong>1.简介<br /></strong>　　偶们这次主要说说怎么由Lua定义函数, 然后在C或者C++中调用. 这里偶们<br />　　暂不涉及C++的对象问题, 只讨论调用函数的参数, 返回值和全局变量的使用.<!--DVNEWS_AD_BEGIN--><br /><br />　　<b>2.程序</b><br />　　这里偶们在e12.lua里先定义一个简单的add(), x,y为加法的两个参数,<br />　　return 直接返回相加后的结果.<br />　　<br />　　例e12.lua<br />　　-- add two numbers<br />　　function add ( x, y )<br />　　return x + y<br />　　end<br />　　<br />　　在前一次里, 偶们说到 lua_dofile() 可以直接在C中执行lua文件. 因为偶们<br />　　这个程序里只定义了一个add()函数, 所以程序执行后并不直接结果, 效果相当<br />　　于在C中定义了一个函数一样.<br />　　<br />　　Lua的函数可以有多个参数, 也可以有多个返回值, 这都是由栈(stack)实现的.<br />　　需要调用一个函数时, 就把这个函数压入栈, 然后顺序压入所有参数, 然后用<br />　　lua_call()调用这个函数. 函数返回后, 返回值也是存放在栈中. 这个过程和<br />　　汇编执行函数调用的过程是一样的.<br />　　<br />　　例e13.cpp 是一个调用上面的Lua函数的例子<br />　　#include <stdio.h><br />　　<br />　　extern "C" { // 这是个C++程序, 所以要extern "C",<br />　　　　 // 因为lua的头文件都是C格式的<br />　　#include "lua.h"<br />　　#include "lualib.h"<br />　　#include "lauxlib.h"<br />　　}<br />　　<br />　　/* the Lua interpreter */<br />　　lua_State* L;<br />　　<br />　　int luaadd ( int x, int y )<br />　　{<br />　　int sum;<br />　　<br />　　/* the function name */<br />　　lua_getglobal(L, "add");<br />　　<br />　　/* the first argument */<br />　　lua_pushnumber(L, x);<br />　　<br />　　/* the second argument */<br />　　lua_pushnumber(L, y);<br />　　<br />　　/* call the function with 2<br />　　　 arguments, return 1 result */<br />　　lua_call(L, 2, 1);<br />　　<br />　　/* get the result */<br />　　sum = (int)lua_tonumber(L, -1);<br />　　lua_pop(L, 1);<br />　　<br />　　return sum;<br />　　}<br />　　<br />　　int main ( int argc, char *argv[] )<br />　　{<br />　　int sum;<br />　　<br />　　/* initialize Lua */<br />　　L = lua_open();<br />　　<br />　　/* load Lua base libraries */<br />　　lua_baselibopen(L);<br />　　<br />　　/* load the script */<br />　　lua_dofile(L, "e12.lua");<br />　　<br />　　/* call the add function */<br />　　sum = luaadd( 10, 15 );<br />　　<br />　　/* print the result */<br />　　printf( "The sum is %d\n", sum );<br />　　<br />　　/* cleanup Lua */<br />　　lua_close(L);<br />　　<br />　　return 0;<br />　　}<br />　　<br />　　程序说明:<br />　　main中过程偶们上次已经说过了, 所以这次只说说luaadd的过程<br />　　* 首先用lua_getglobal()把add函数压栈<br />　　* 然后用lua_pushnumber()依次把x,y压栈<br />　　* 然后调用lua_call(), 并且告诉程序偶们有两个参数一个返回值<br />　　* 接着偶们从栈顶取回返回值, 用lua_tonumber()<br />　　* 最后偶们用lua_pop()把返回值清掉<br />　　<br />　　运行结果:<br />　　The sum is 25<br />　　<br />　　编译方法<br />　　Linux下把程序存成e13.cpp<br />　　g++ e13.cpp -llua -llualib -o e13<br />　　./e13<br />　　<br />　　VC下编译方法<br />　　* 首先建立一个空的Win32 Console Application Project<br />　　* 把e13.cpp加入工程中<br />　　* 点project setting,然后设置link选项, 再加上lua.lib lualib.lib两个额外的库<br />　　* 最后编译<br />　　<br />　　建立好的project可以在这里下载<br />　　VC http://tonyandpaige.com/tutorials/luaadd.zip<br />　　Linux http://tonyandpaige.com/tutorials/luaadd.tar.gz<br />　　<br />　　<b>3.全局变量</b><br />　　上面偶们用到了lua_getglobal()但并没有详细讲, 这里偶们再举两个小例子来说下全局变量<br />　　lua_getglobal()的作用就是把lua中全局变量的值压入栈<br />　　lua_getglobal(L, "z");<br />　　z = (int)lua_tonumber(L, 1);<br />　　lua_pop(L, 1);<br />　　假设Lua程序中定义了一个全局变量z, 这段小程序就是把z的值取出放入C的变量z中.<br />　　<br />　　另外Lua中还有一个对应的函数lua_setglobal(), 作用是用栈顶的值填充指定的全局变量<br />　　lua_pushnumber(L, 10);<br />　　lua_setglobal(L, "z");<br />　　例如这段小程序就是把lua中的全局变量z设为10, 如果lua中未定义z的话, 就会自动创建一个<br />　　全局变量z并设为10.<br />　　<br />　　<b>4.试试看</b><br />　　自己写个函数用C/C++来调用下试试<br /><br /><font size="6"><strong>七.调用C/C++函数</strong></font><br /><br /><strong>1.前言<br /></strong>　　上次偶说到从C/C++中调用Lua的函数, 然后就有朋友问从Lua中如何调用C/C++的<br />　　函数, 所以偶们这次就来说说这个问题. 首先偶们会在C++中建立一个函数, 然后<!--DVNEWS_AD_BEGIN--><br />　　告知Lua有这个函数, 最后再执行它. 另外, 由于函数不是在Lua中定义的, 所以<br />　　无法确定函数的正确性, 可能在调用过程中会出错, 因此偶们还会说说Lua出错处<br />　　理的问题.<br />　　<br />　　<b>2.Lua中调用C函数</b><br />　　在lua中是以函数指针的形式调用函数, 并且所有的函数指针都必须满足如下此种<br />　　类型:<br />　　typedef int (*lua_CFunction) (lua_State *L);<br />　　<br />　　也就是说, 偶们在C++中定义函数时必须以lua_State为参数, 以int为返回值才能<br />　　被Lua所调用. 但是不要忘记了, 偶们的lua_State是支持栈的, 所以通过栈可以<br />　　传递无穷个参数, 大小只受内存大小限制. 而返回的int值也只是指返回值的个数<br />　　真正的返回值都存储在lua_State的栈中. 偶们通常的做法是做一个wrapper, 把<br />　　所有需要调用的函数都wrap一下, 这样就可以调用任意的函数了.<br />　　<br />　　下面这个例子是一个C++的average()函数, 它将展示如何用多个参数并返回多个值<br />　　<br />　　例e14.cpp<br />　　#include <stdio.h><br />　　<br />　　extern "C" {<br />　　#include "lua.h"<br />　　#include "lualib.h"<br />　　#include "lauxlib.h"<br />　　}<br />　　<br />　　/* the Lua interpreter */<br />　　lua_State* L;<br />　　<br />　　static int average(lua_State *L)<br />　　{<br />　　/* get number of arguments */<br />　　int n = lua_gettop(L);<br />　　double sum = 0;<br />　　int i;<br />　　<br />　　/* loop through each argument */<br />　　for (i = 1; i &lt;= n; i++)<br />　　{<br />　　/* total the arguments */<br />　　sum += lua_tonumber(L, i);<br />　　}<br />　　<br />　　/* push the average */<br />　　lua_pushnumber(L, sum / n);<br />　　<br />　　/* push the sum */<br />　　lua_pushnumber(L, sum);<br />　　<br />　　/* return the number of results */<br />　　return 2;<br />　　}<br />　　<br />　　int main ( int argc, char *argv[] )<br />　　{<br />　　/* initialize Lua */<br />　　L = lua_open();<br />　　<br />　　/* load Lua base libraries */<br />　　lua_baselibopen(L);<br />　　<br />　　/* register our function */<br />　　lua_register(L, "average", average);<br />　　<br />　　/* run the script */<br />　　lua_dofile(L, "e15.lua");<br />　　<br />　　/* cleanup Lua */<br />　　lua_close(L);<br />　　<br />　　return 0;<br />　　}<br />　　<br />　　例e15.lua<br />　　-- call a C++ function<br />　　<br />　　avg, sum = average(10, 20, 30, 40, 50)<br />　　<br />　　print("The average is ", avg)<br />　　print("The sum is ", sum)<br />　　<br />　　<br />　　程序说明:<br />　　* lua_gettop()的作用是返回栈顶元素的序号. 由于Lua的栈是从1开始编号的,<br />　　　所以栈顶元素的序号也相当于栈中的元素个数. 在这里, 栈中元素的个数就<br />　　　是传入的参数个数.<br />　　* for循环计算所有传入参数的总和. 这里用到了数值转换lua_tonumber().<br />　　* 然后偶们用lua_pushnumber()把平均值和总和push到栈中.<br />　　* 最后, 偶们返回2, 表示有两个返回值.<br />　　* 偶们虽然在C++中定义了average()函数, 但偶们的Lua程序并不知道, 所以需<br />　　　要在main函数中加入<br />　　<br />　　　 /* register our function */<br />　　lua_register(L, "average", average);<br />　　<br />　　　这两行的作用就是告诉e15.lua有average()这样一个函数.<br />　　* 这个程序可以存成cpp也可以存成c, 如果以.c为扩展名就不需要加extern "C"<br />　　<br />　　编译的方法偶们上次说过了, 方法相同.<br />　　e15.lua执行的方法只能用上例中的C++中执行, 而不能用命令行方式执行.<br />　　<br />　　<b>3.错误处理</b><br />　　在上例中, 偶们没有对传入的参数是否为数字进行检测, 这样做不好. 所以这里偶<br />　　们再加上错误处理的片断.<br />　　<br />　　把这段加在for循环之内:<br />　　if (!lua_isnumber(L, i)) {<br />　　lua_pushstring(L, "Incorrect argument to 'average'");<br />　　lua_error(L);<br />　　}<br />　　这段的作用就是检测传入的是否为数字.<br />　　<br />　　加上这段之后, 偶们debug的时候就会简单许多. 对于结合两种语言的编程, 它们之<br />　　间传递数据的正确性检测是非常重要的.<br />　　<br />　　这里有别人写好的例子:<br />　　VC的 http://tonyandpaige.com/tutorials/luaavg.zip<br />　　Linux的 http://tonyandpaige.com/tutorials/luaavg.tar.gz<br />　　 </stdio.h></stdio.h></lualib.h></lualib.h></lua.h></stdio.h></lua.h></lua.h></stdio.h><img src ="http://www.cppblog.com/mybios/aggbug/15356.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-18 14:34 <a href="http://www.cppblog.com/mybios/archive/2006/11/18/15356.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】如何在C++中集成LUA脚本(LuaWrapper For C++篇)</title><link>http://www.cppblog.com/mybios/archive/2006/11/18/15339.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 18 Nov 2006 02:00:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/18/15339.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15339.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/18/15339.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15339.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15339.html</trackback:ping><description><![CDATA[
		<p>作者： 沐枫 （第二人生成员）<br />版权所有转载请注明原出处<br />主页：第二人生 <a href="http://www.d2-life.com/" target="_blank">http://www.d2-life.com</a><br />　　　<a href="http://www.d2-life.com/LBS/blogview.asp?logID=41" target="_blank">http://www.d2-life.com/LBS/blogview.asp?logID=41</a><br /><br />为什么要用Lua作脚本？<br />　　使用Lua作脚本，主要是因为它小巧玲珑（体积小，运行快），而且它的语法又比较简单明了。不过，使用LuaAPI将Lua引擎集成到程序中，确实有一些不方便——用落木随风网友的话来说，就是"就象用汇编"。当然，现在你不用再这么辛苦了，因为你可以使用LuaWrapper For C++。使用这个工具，在C++中集成Lua脚本就是轻而易举的事。你原有的C++函数和类，几乎不需要任何改变，就可以与Lua脚本共享。<br />　　我们接下来，用实例来说明，如何用LuaWrapper来集成Lua脚本到你的程序中去。<br /><br />1.  创建Lua引擎<br />　　LuaWrap lua; 或者 LuaWrap* lua = new LuaWrap;<br />　　创建一个LuaWrap对象，就是创建一个Lua脚本引擎。并且根据Lua的特性，你可以创建任意多个Lua引擎，甚至可以分布在不同的线程当中。<br /><br />2.  装载并执行脚本程序<br />　　你可以从缓冲区中装载Lua脚本：<br />　　lua.LoadString(<br />　　　　"print('Hello World')"<br />　　);<br />　　当然，你也可以从文件中装入，并执行Lua脚本：<br />　　Lua.LoadFile("./test.lua");<br />　　Lua的脚本，可以是源代码，也可以经过编译后的中间代码。也许你对编译后的中间代码更感兴趣——如果你不希望让源代码赤裸裸的袒露在大家的眼前。<br /><br />3.  获取和设置Lua变量<br />　　能够获取和设置脚本变量的内容，是一个最基本的功能。你可以使用GetGlobal和SetGlobal函数来做到这一点：<br />　　(1)  获取变量：<br />　　　　int a = lua.GetGlobal&lt;int&gt;("a");<br />　　　　LuaTable table = lua.GetGlobal&lt;LuaTable&gt;("t");<br />　　　　这里，&lt;&gt; 里头的类型，就是想要的变量的类型。<br />　　(2)  设置变量：<br />　　　　lua.SetGlobal("a", a); <br />　　　　lua.SetGlobal("t", table);<br /><br />4.  调用Lua函数<br />　　使用Call函数，就可以很简单的从你的程序中调用Lua函数：<br />　　lua.Call&lt;void&gt;("print", "Hello World");<br />　　int sum = lua.Call&lt;int&gt;("add", 2, 3);<br />　　这里，&lt;&gt; 里头的类型是返回值的类型。<br /><br />5.  如何让Lua也能调用C++的函数<br />　　精采的地方来了。假如有下面这样的一个函数：<br />　　int add(int a, int b)<br />　　{<br />　　　　return a + b;<br />　　}<br />　　如果想让它能够让Lua使用，只需将它注册到Lua引擎当中就可以了：<br />　　lua.RegisterFunc("add", int(int,int), add);<br />　　这样，Lua中就可以用直接使用了：<br />　　（Lua脚本）sum = add(1, 3) <br /><br />　　(*) RegisterFunc的功能，就是让你把C++的函数注册到Lua中，供Lua脚本使用。<br />　　　　第一个参数，是想要在Lua中用的函数名。<br />　　　　第二个参数，是C++中函数的原型； C++允许函数重载的，你可以使用函数原型，来选择需要注册到Lua引擎中的那个函数。<br />　　　　第三个参数，就是C++中函数的指针了。<br /><br />6.  如何能让C++的类在Lua中使用<br />　　我们先看看下面这个C++类：<br />class MyArray<br />{<br />  std::vector&lt;double&gt; array;<br />public:<br />  void setvalue(int index, double value);<br />  double getvalue(int index);<br />  int size();<br />  const char* ToString();<br />};<br /><br />　　你准备要让Lua能够自由访问并操作这个类。很简单，你只需增加几个宏定义就可以了：<br /><br />class MyArray<br />{<br />  std::vector&lt;double&gt; array;<br />public:<br />  void setvalue(int index, double value);<br />  double getvalue(int index);<br />  int size();<br />  const char* ToString();<br />  // 将一个 class 作为一个 Lua 对象是很容易的，只需要增加以下宏定义。<br />  DEFINE_TYPENAME("My.array");<br />  BEGIN_REGLUALIB("array")<br />      LUALIB_ITEM_create("new", MyArray )  // 创建MyArray (注：由于发表的原因，create应为全部大写)<br />      LUALIB_ITEM_DESTROY("del", MyArray )  // 消除MyArray。<br />  END_REGLUALIB()<br />  BEGIN_REGLUALIB_MEMBER()<br />    LUALIB_ITEM_FUNC("size", int (MyArray*), &amp;MyArray::size)<br />    LUALIB_ITEM_FUNC("__getindex", double(MyArray*, int), &amp;MyArray::getvalue)  <br />    LUALIB_ITEM_FUNC("__newindex", void (MyArray*, int, double), &amp;MyArray::setvalue)<br />    LUALIB_ITEM_FUNC("__tostring", const char* (MyArray*), &amp;MyArray::ToString)<br />    LUALIB_ITEM_DESTROY("__gc", MyArray )   // 垃圾收集时消除对象用。<br />  END_REGLUALIB_MEMBER()<br />};<br /><br />　　只要有了这些宏定义，这个类就是可以在Lua中使用的类了，我们就可以在Lua中注册这个类了：<br />　　lua.Register&lt;MyArray&gt;()<br /><br />　　这样注册以后，我们在Lua中就可以使用这个类了：<br />　　a = array.new()  -- 创建对象，相当于 a = new Myarray<br />　　a[1] = 10  -- 调用__newindex，也就是C++中的 a-&gt;setvalue(1, 10)<br />　　a[2] = 20  -- 调用__newindex，也就是C++中的 a-&gt;setvalue(2, 20)<br />　　print(<br />　　　　a,  -- 调用 __tostring，也就是C++中的 a-&gt;ToString()<br />　　　　a:size(), -- 相当于C++中的 a-&gt;size()<br />　　　　a[1], -- 调用__getindex，也就是C++中的a-&gt;getvalue(1)<br />　　　　a[2]) --调用__getindex，也就是C++中的a-&gt;getvalue(2)<br />　　array.del(a)  -- 清除对象，相当于 delete a<br />　　a = nil  -- 清空 a，很象C++中的 a = NULL<br /><br />　　当然，你也可以不用del这个对象，而是等待Lua帮你自动进行垃圾回收。在Lua进行垃圾回收时，它会自动调用这个对象的 __gc ，相当于 delete。<br /><br />　　那么，在C++中要创建MyArray对象，并且传递给Lua全局变量怎么办？就象前面讲过的一样，使用SetGlobal：<br />　　MyArray* a = new MyArray; <br />　　lua.SetGlobal("a", a);<br />　　要获取该对象，同样的，应该使用GetGlobal：<br />　　MyArray* a = lua.GetGlobal&lt;MyArray&gt;("a");<br />　　<br />　　对于传递给Lua的对象，就让Lua来管理该对象的生存周期好了。如果你非要删除它的话，你可以使用DelGlobalObject：<br />　　lua.DelGlobalObject&lt;MyArray&gt;("a");<br />　　不过这么做的话，你应当明白你在做什么，因为在Lua的脚本中，可能已经在多处引用了这个对象了。删除了其中一个，将导致其它引用对象失效，从而可能引致系统崩溃。<br /><br />　　(1)  DEFINE_TYPENAME("My.array");<br />　　　　定义类型的名称。在Lua中，这个类型名称是唯一用来识别C++类型的，你必须为不同的对象给予不同的名称。<br /><br />　　(2)  BEGIN_REGLUALIB("array") … END_REGLUALIB()<br />　　　　你可以为一个对象定义一个程序库，"array"就是程序库的名字。在程序库中定义的函数是全局函数，在Lua中，使用该函数，需要在函数前加上库的名字，如：array.new（）。通常，程序库会包含创建对象的方法。如：<br />　　　　LUALIB_ITEM_create("new", MyArray )  // 创建MyArray (注：由于发表的原因，create应为全部大写)<br />　　　　这样子，你才能在Lua中创建MyArray：<br />　　　　a = array.new()<br />　　<br />　　　　你也可以选择增加一个删除对象操作：<br />　　　　LUALIB_ITEM_DESTROY("del", MyArray )   // 删除MyArray<br />　　　　这样，你就可以直接删除一个对象了：<br />　　　　array.del(a)<br /><br />　　(3)  BEGIN_REGLUALIB_MEMBER() …END_REGLUALIB_MEMBER()<br />　　　　在此处，你可以定义对象的成员函数，也可以重载对象的操作符——是的，就象C++的operator重载。例如：<br />　　　　LUALIB_ITEM_FUNC("__newindex", void (MyArray*, int, double), &amp;MyArray::setvalue)<br />　　　　就是重载 operator[] 操作符。Lua中可重载的操作符还有许多，如：<br /><br />　　　　__getindex：操作符[]，支持读取访问，如 v = a[10]<br />　　　　__newindex：操作符[]，支持赋值访问，如 a[10] = 1.22<br />　　　　__tostring：将变量转换成字串__add：等同于operator +<br />　　　　__add：操作符 ＋<br />　　　　__sub：操作符 –<br />　　　　__mul：操作符 ×<br />　　　　__div：操作符 ÷<br />　　　　__pow：操作符 ^ (乘方)<br />　　　　__unm：一元操作符 –<br />　　　　__concat：操作符 .. (字符串连接)<br />　　　　__eq：操作符 == (a ~= b等价于 not a == b)<br />　　　　__lt：操作符 &lt; (a &gt; b 等价于 b &lt; a)<br />　　　　__le：操作符 &lt;= (a &gt;= b 等价于 b &lt;= a，要注意的是，如果没有定义"__le"，则Lua将会尝试将a&lt;=b 转换成 not (b &lt; a) )<br /><br />　　　　__gc：在垃圾回收时调用此函数，相当于C++的析构函数。强烈建议定义此操作符，以免造成内存泄漏等情况。比如：<br />　　　　LUALIB_ITEM_DESTROY("__gc", MyArray )   // 垃圾收集时消除对象用。<br /><br />　　　　(注) 这里要说明一下，在lua中，访问索引操作符是__index，不是__getindex，在luaWrapper库中，为了方便使用，将其映射为__getindex，同时，对__index的定义将会被忽略。<br /><br />　　　　就这么简单。假如你已经有现成的类，而你没有修改该类的权力，如何将其加入到Lua中呢？答案就是，继承它，将把派生类加入到Lua中。<br /><br />结束语<br />　　LuaWrapper 需要用到boost库的支持：boost/type_traits.hpp, boost/function.hpp, boost/bind.hpp，它使用了C++的模板部份特化，因此，C++编译器如果不支持此特性，将无法编译。目前支持此特性的编译器已经有很多。在VisualStudo产品系列中，只有VC7.1能支持此特性，因此，您如果正在使用VisualStudio，请确认你用的是VisualStudio2003。<br />　　如果你觉得 LuaWrapper For C++ 能够帮助你，我会感觉很荣幸。我很愿意将这个程序库分享给大家。顺便一提的是，如果你在使用过程中发现BUG，或是有好的建议，希望您能与我联系。你在使用过程中，请不要删除文件中的署名信息；如果你修改了程序库，请您在修改的文件中加入您的修改说明。当然，我会非常欢迎您能将修改后的程序回馈给我。我会继续优化并完善它。<br /><br />=============================================================<br /><br /><a href="http://www.d2-life.com/lbs/attachments/month_200407/22_1xp4LuaWrapper.zip"><img src="http://www.d2-life.com/lbs/images/icon_save.gif" align="absMiddle" border="0" /><b>File:</b> Click Here Download: LuaWrapper For C++</a><br /><a href="http://www.d2-life.com/lbs/attachments/month_200407/22_85waTestLua.zip"><img src="http://www.d2-life.com/lbs/images/icon_save.gif" align="absMiddle" border="0" /><b>File:</b> Click Here Download: LuaWrapper test program</a><br /><br />=============================================================</p>
<img src ="http://www.cppblog.com/mybios/aggbug/15339.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-18 10:00 <a href="http://www.cppblog.com/mybios/archive/2006/11/18/15339.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】Lua 程序设计初步</title><link>http://www.cppblog.com/mybios/archive/2006/11/18/15338.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 18 Nov 2006 01:48:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/18/15338.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15338.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/18/15338.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15338.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15338.html</trackback:ping><description><![CDATA[作者： 沐枫 （第二人生成员）<br />版权所有转载请注明原出处<br />主页：第二人生 <a href="http://www.d2-life.com/" target="_blank"><font color="#002c99">http://www.d2-life.com</font></a><br />　　　<a href="http://www.d2-life.com/LBS/blogview.asp?logID=39" target="_blank"><font color="#002c99">http://www.d2-life.com/LBS/blogview.asp?logID=39</font></a><br /><br />　　在这篇文章中，我想向大家介绍如何进行Lua程序设计。我假设大家都学过至少一门编程语言，比如Basic或C，特别是C。因为Lua的最大用途是在宿主程序中作为脚本使用的。<br />　　Lua 的语法比较简单，学习起来也比较省力，但功能却并不弱。<br />　　在Lua中，一切都是变量，除了关键字。请记住这句话。<br /><br />I.  首先是注释<br />　　写一个程序，总是少不了注释的。<br />　　在Lua中，你可以使用单行注释和多行注释。<br />　　单行注释中，连续两个减号"--"表示注释的开始，一直延续到行末为止。相当于C++语言中的"//"。<br />　　多行注释中，由"--[["表示注释开始，并且一直延续到"]]"为止。这种注释相当于C语言中的"/*…*/"。在注释当中，"[["和"]]"是可以嵌套的。<br />II.  Lua编程<br />　　经典的"Hello world"的程序总是被用来开始介绍一种语言。在Lua中，写一个这样的程序很简单：<br />　　print("Hello world")<br />　　在Lua中，语句之间可以用分号"；"隔开，也可以用空白隔开。一般来说，如果多个语句写在同一行的话，建议总是用分号隔开。<br />　　Lua 有好几种程序控制语句，如：<br /><br />　　条件控制：if 条件 then … elseif 条件 then … else … end<br />　　While循环：while 条件 do … end<br />　　Repeat循环：repeat … until 条件<br />　　For循环：for 变量 = 初值，终点值，步进 do … end<br />　　For循环：for 变量1，变量2，… ，变量N in表或枚举函数 do … end<br /><br />　　注意一下，for的循环变量总是只作用于for的局部变量，你也可以省略步进值，这时候，for循环会使用1作为步进值。<br />　　你可以用break来中止一个循环。<br />　　如果你有程序设计的基础，比如你学过Basic，C之类的，你会觉得Lua也不难。但Lua有几个地方是明显不同于这些程序设计语言的，所以请特别注意。<br /><br />　　．语句块<br />　　　　语句块在C++中是用"{"和"}"括起来的，在Lua中，它是用do 和 end 括起来的。比如： <br />　　　　do print("Hello") end<br />　　　　你可以在 函数 中和 语句块 中定局部变量。<br /><br />　　．赋值语句<br />　　　　赋值语句在Lua被强化了。它可以同时给多个变量赋值。<br />　　　　例如：<br />　　　　a,b,c,d=1,2,3,4<br />　　　　甚至是：<br />　　　　a,b=b,a  -- 多么方便的交换变量功能啊。<br />　　　　在默认情况下，变量总是认为是全局的。假如你要定义局部变量，则在第一次赋值的时候，需要用local说明。比如：<br />　　　　local a,b,c = 1,2,3  -- a,b,c都是局部变量<br /><br />　　．数值运算<br />　　　　和C语言一样，支持 +, -, *, /。但Lua还多了一个"^"。这表示指数乘方运算。比如2^3 结果为8, 2^4结果为16。<br />　　　　连接两个字符串，可以用".."运处符。如：<br />　　　　"This a " .. "string." -- 等于 "this a string"<br /><br />　　．比较运算<br />　　　　&lt; &gt; &lt;= &gt;= == ~=<br />　　　　分别表示 小于，大于，不大于，不小于，相等，不相等<br />　　　　所有这些操作符总是返回true或false。<br />　　　　对于Table，Function和Userdata类型的数据，只有 == 和 ~=可以用。相等表示两个变量引用的是同一个数据。比如：<br />　　　　a={1,2}<br />　　　　b=a<br />　　　　print(a==b, a~=b)  -- true, false<br />　　　　a={1,2}<br />　　　　b={1,2}<br />　　　　print(a==b, a~=b)  -- false, true<br /><br />　　．逻辑运算<br />　　　　and, or, not<br />　　　　其中，and 和 or 与C语言区别特别大。<br />　　　　在这里，请先记住，在Lua中，只有false和nil才计算为false，其它任何数据都计算为true，0也是true！<br />　　　　and 和 or的运算结果不是true和false，而是和它的两个操作数相关。<br />　　　　a and b：如果a为false，则返回a；否则返回b<br />　　　　a or b：如果 a 为true，则返回a；否则返回b<br /><br />　　　　举几个例子：<br />　　　　 print(4 and 5) --&gt; 5<br />　　　　 print(nil and 13) --&gt; nil<br />　　　　 print(false and 13) --&gt; false<br />　　　　 print(4 or 5) --&gt; 4<br />　　　　 print(false or 5) --&gt; 5<br /><br />　　　　在Lua中这是很有用的特性，也是比较令人混洧的特性。<br />　　　　我们可以模拟C语言中的语句：x = a? b : c，在Lua中，可以写成：x = a and b or c。<br />　　　　最有用的语句是： x = x or v，它相当于：if not x then x = v end 。<br /><br />　　．运算符优先级，从高到低顺序如下：<br />　　　　^<br />　　　　not - （一元运算）<br />　　　　 * /<br />　　　　 + -<br />　　　　 ..（字符串连接）<br />　　　　 &lt; &gt; &lt;= &gt;= ~= ==<br />　　　　 and<br />　　　　 or<br /><br />III.  关键字<br />　　关键字是不能做为变量的。Lua的关键字不多，就以下几个：<br />　　and break do else elseif<br />　　end false for function if<br />　　in local nil not or<br />　　repeat return then true until　while<br /><br />IV.  变量类型<br />　　怎么确定一个变量是什么类型的呢？大家可以用type()函数来检查。Lua支持的类型有以下几种：<br /><br />　　Nil  空值，所有没有使用过的变量，都是nil。nil既是值，又是类型。<br />　　Boolean  布尔值<br />　　Number  数值，在Lua里，数值相当于C语言的double<br />　　String  字符串，如果你愿意的话，字符串是可以包含'\0'字符的<br />　　Table  关系表类型，这个类型功能比较强大，我们在后面慢慢说。<br />　　Function  函数类型，不要怀疑，函数也是一种类型，也就是说，所有的函数，它本身就是一个变量。<br />　　Userdata  嗯，这个类型专门用来和Lua的宿主打交道的。宿主通常是用C和C++来编写的，在这种情况下，Userdata可以是宿主的任意数据类型，常用的有Struct和指针。<br />　　Thread　　  线程类型，在Lua中没有真正的线程。Lua中可以将一个函数分成几部份运行。如果感兴趣的话，可以去看看Lua的文档。<br /><br />V.  变量的定义<br />　　所有的语言，都要用到变量。在Lua中，不管你在什么地方使用变量，都不需要声明，并且所有的这些变量总是全局变量，除非，你在前面加上"local"。<br />　　这一点要特别注意，因为你可能想在函数里使用局部变量，却忘了用local来说明。<br />　　至于变量名字，它是大小写相关的。也就是说，A和a是两个不同的变量。<br />　　定义一个变量的方法就是赋值。"＝"操作就是用来赋值的<br />　　我们一起来定义几种常用类型的变量吧。<br />　　A.  Nil<br />　　　　正如前面所说的，没有使用过的变量的值，都是Nil。有时候我们也需要将一个变量清除，这时候，我们可以直接给变量赋以nil值。如：<br />　　　　var1=nil  -- 请注意 nil 一定要小写<br /><br />　　B.  Boolean<br />　　　　布尔值通常是用在进行条件判断的时候。布尔值有两种：true 和 false。在Lua中，只有false和nil才被计算为false，而所有任何其它类型的值，都是true。比如0，空串等等，都是true。不要被C语言的习惯所误导，0在Lua中的的确确是true。你也可以直接给一个变量赋以Boolean类型的值，如：<br />　　　　varboolean = true<br /><br />　　C.  Number<br />　　　　在Lua中，是没有整数类型的，也不需要。一般情况下，只要数值不是很大（比如不超过100,000,000,000,000），是不会产生舍入误差的。在很多CPU上，实数的运算并不比整数慢。<br />　　　　实数的表示方法，同C语言类似，如：<br />　　　　4 0.4 4.57e-3 0.3e12 5e+20<br /><br />　　D.  String<br />　　　　字符串，总是一种非常常用的高级类型。在Lua中，你可以非常方便的定义很长很长的字符串。<br />　　　　字符串在Lua中有几种方法来表示，最通用的方法，是用双引号或单引号来括起一个字符串的，如：<br />　　　　"This is a string."<br />　　　　和C语言相同的，它支持一些转义字符，列表如下：<br />　　　　\a  bell<br />　　　　\b  back space<br />　　　　\f  form feed<br />　　　　\n  newline<br />　　　　\r  carriage return<br />　　　　\t  horizontal tab<br />　　　　\v  vertical tab<br />　　　　\\  backslash<br />　　　　\"  double quote<br />　　　　\'  single quote<br />　　　　\[  left square bracket<br />　　　　\]  right square bracket<br /><br />　　　　由于这种字符串只能写在一行中，因此，不可避免的要用到转义字符。加入了转义字符的串，看起来实在是不敢恭维，比如：<br />　　　　"one line\nnext line\n\"in quotes\", 'in quotes'"<br />　　　　一大堆的"\"符号让人看起来很倒胃口。如果你与我有同感，那么，我们在Lua中，可以用另一种表示方法：用"[["和"]]"将多行的字符串括起来，如：<br />　　　　page = [[<br />　　　　&lt;HTML&gt;<br />　　　　　　&lt;HEAD&gt;<br />　　　　　　　　&lt;TITLE&gt;An HTML Page&lt;/TITLE&gt;<br />　　　　　　&lt;/HEAD&gt;<br />　　　　　　&lt;BODY&gt;<br />　　　　　　　　&lt;A HREF="<a href="">lua</a>' target=_blank&gt;<font color="#002c99">http://www.lua.org"&gt;Lua&lt;/A&gt;</font><br />　　　　　　　　[[a text between double brackets]]<br />　　　　　　&lt;/BODY&gt;<br />　　　　&lt;/HTML&gt;<br />　　　　]]<br /><br />　　　　值得注意的是，在这种字符串中，如果含有单独使用的"[["或"]]"就仍然得用"\["或"\]"来避免歧义。当然，这种情况是极少会发生的。<br /><br />　　E.  Table<br />　　　　关系表类型，这是一个很强大的类型。我们可以把这个类型看作是一个数组。只是C语言的数组，只能用正整数来作索引；在Lua中，你可以用任意类型来作数组的索引，除了nil。同样，在C语言中，数组的内容只允许一种类型；在Lua中，你也可以用任意类型的值来作数组的内容，除了nil。<br />　　　　Table的定义很简单，它的主要特征是用"{"和"}"来括起一系列数据元素的。比如：<br /><br />　　　　T1 = {}  -- 定义一个空表<br />　　　　T1[1]=10  -- 然后我们就可以象C语言一样来使用它了。<br />　　　　T1["John"]={Age=27, Gender="Male"}<br />　　　　这一句相当于：<br />　　　　T1["John"]={}  -- 必须先定义成一个表，还记得未定义的变量是nil类型吗<br />　　　　T1["John"]["Age"]=27<br />　　　　T1["John"]["Gender"]="Male"<br />　　　　当表的索引是字符串的时候，我们可以简写成：<br />　　　　T1.John={}<br />　　　　T1.John.Age=27<br />　　　　T1.John.Gender="Male"<br />　　　　或<br />　　　　T1.John{Age=27, Gender="Male"}<br />　　　　这是一个很强的特性。<br /><br />　　　　在定义表的时候，我们可以把所有的数据内容一起写在"{"和"}"之间，这样子是非常方便，而且很好看。比如，前面的T1的定义，我们可以这么写：<br /><br />　　　　T1=<br />　　　　{<br />　　　　　　10,  -- 相当于 [1] = 10<br />　　　　　　[100] = 40,<br />　　　　　　John=  -- 如果你原意，你还可以写成：["John"] =<br />　　　　　　{<br />　　　　　　　　Age=27,   -- 如果你原意，你还可以写成：["Age"] =27<br />　　　　　　　　Gender=Male   -- 如果你原意，你还可以写成：["Gender"] =Male<br />　　　　　　},<br />　　　　　　20  -- 相当于 [2] = 20<br />　　　　}<br /><br />　　　　看起来很漂亮，不是吗？我们在写的时候，需要注意三点：<br />　　　　第一，所有元素之间，总是用逗号"，"隔开；<br />　　　　第二，所有索引值都需要用"["和"]"括起来；如果是字符串，还可以去掉引号和中括号；<br />　　　　第三，如果不写索引，则索引就会被认为是数字，并按顺序自动从1往后编；<br /><br />　　　　表类型的构造是如此的方便，以致于常常被人用来代替配置文件。是的，不用怀疑，它比ini文件要漂亮，并且强大的多。<br /><br />　　F.  Function<br />　　　　函数，在Lua中，函数的定义也很简单。典型的定义如下：<br />　　　　function add(a,b)  -- add 是函数名字，a和b是参数名字<br />　　　　 return a+b  -- return 用来返回函数的运行结果<br />　　　　end<br /><br />　　　　请注意，return语言一定要写在end之前。假如你非要在中间放上一句return，那么请写成：do return end。<br />　　　　还记得前面说过，函数也是变量类型吗？上面的函数定义，其实相当于：<br />　　　　add = function (a,b) return a+b end<br />　　　　当你重新给add赋值时，它就不再表示这个函数了。你甚至可以赋给add任意数据，包括nil （这样，你就清除了add变量）。Function是不是很象C语言的函数指针呢？<br /><br />　　　　和C语言一样，Lua的函数可以接受可变参数个数，它同样是用"…"来定义的，比如：<br />　　　　function sum (a,b,…)<br />　　　　如果想取得…所代表的参数，可以在函数中访问arg局部变量（表类型）得到。<br />　　　　如 sum(1,2,3,4)<br />　　　　则，在函数中，a = 1, b = 2, arg = {3, 4}<br />　　　　更可贵的是，它可以同时返回多个结果，比如：<br />　　　　function s()<br />　　　　　　return 1,2,3,4<br />　　　　end<br />　　　　a,b,c,d = s()  -- 此时，a = 1, b = 2, c = 3, d = 4<br /><br />　　　　前面说过，表类型可以拥有任意类型的值，包括函数！因此，有一个很强大的特性是，拥有函数的表，哦，我想更恰当的应该说是对象吧。Lua可以使用面向对象编程了。不信？那我举例如下：<br /><br />　　　　t =<br />　　　　{<br />　　　　 Age = 27<br />　　　　 add = function(self, n) self.Age = self.Age+n end<br />　　　　}<br />　　　　print(t.Age)  -- 27<br />　　　　t.add(t, 10)<br />　　　　print(t.Age)  -- 37<br /><br />　　　　不过，t.add(t,10) 这一句实在是有点土对吧？没关系，在Lua中，你可以简写成：<br />　　　　t:add(10)    -- 相当于 t.add(t,10)<br /><br />　　G.  Userdata 和 Thread<br />　　　　这两个类型的话题，超出了本文的内容，就不打算细说了。<br /><br />VI.  结束语<br />　　就这么结束了吗？当然不是，接下来，需要用Lua解释器，来帮助你理解和实践了。这篇小文只是帮助你大体了解Lua的语法。如果你有编程基础，相信会很快对Lua上手了。<br />　　就象C语言一样，Lua提供了相当多的标准函数来增强语言的功能。使用这些标准函数，你可以很方便的操作各种数据类型，并处理输入输出。有关这方面的信息，你可以参考《Programming in Lua 》一书，你可以在网络上直接观看电子版，网址为：<a href="http://www.lua.org/pil/index.html" target="_blank"><font color="#002c99">http://www.lua.org/pil/index.html</font></a><br />　　当然，Lua的最强大的功能是能与宿主程序亲蜜无间的合作，因此，下一篇文章，我会告诉大家，如何在你的程序中使用Lua语言作为脚本，使你的程序和Lua脚本进行交互。<br /><img src ="http://www.cppblog.com/mybios/aggbug/15338.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-18 09:48 <a href="http://www.cppblog.com/mybios/archive/2006/11/18/15338.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】如何在C++中集成Lua脚本(LuaPlus篇) </title><link>http://www.cppblog.com/mybios/archive/2006/11/18/15337.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 18 Nov 2006 01:46:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/18/15337.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15337.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/18/15337.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15337.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15337.html</trackback:ping><description><![CDATA[
		<div class="imagefix" id="blog">
				<p>
				</p>
				<p>去年我作了一个Lua脚本的C++包装，有许多朋友感兴趣，并尝试使用，我感到受宠若惊。事实上，我作的包装，学习的目的比较强，它还是有许多缺陷的。为了让朋友们少走弯路，我推荐使用LuaPlus作为C++的包装。</p>
				<p>LuaPlus是Lua的C++增强，也就是说，LuaPlus本身就是在Lua的源码上进行增强得来的。用它与C++进行合作，是比较好的一个选择。<br />LuaPlus目前版本为：LuaPlus for Lua 5.01 Distribution Build 1080 (February 28, 2004)。大家可以到<a href="http://luaplus.org/" target="_blank">http://luaplus.org/</a> 站点下载：<br />源码   (<a href="http://wwhiz.com/LuaPlus/LuaPlus50_Build1081.zip" target="_blank">http://wwhiz.com/LuaPlus/LuaPlus50_Build1081.zip</a>)<br />目标码 (<a href="http://wwhiz.com/LuaPlus/LuaPlus50_Build1081_Win32Binaries.zip" target="_blank">http://wwhiz.com/LuaPlus/LuaPlus50_Build1081_Win32Binaries.zip</a>)</p>
				<p>我将在下面说明，如何使用LuaPlus，以及如何更方便的让LuaPlus与C++的类合作无间。</p>
				<p>1. 调用Lua脚本</p>
				<p>    // 创建Lua解释器：<br />    LuaStateOwner state; <br />    <br />    // 执行Lua脚本：<br />    state-&gt;DoString("print('Hello World\n')");<br />    // 载入Lua脚本文件并执行：<br />    state-&gt;DoFile("C:\\test.lua");<br />    // 载入编译后的Lua脚本文件并执行：<br />    state-&gt;DoFile("C:\\test.luac");</p>
				<p>2. 与Lua脚本互相调用</p>
				<p>    // 为Lua脚本设置变量<br />    state-&gt;GetGlobals().SetNumber("myvalue", 123456);<br />    // 获得Lua变量的值<br />    int myvalue = state-&gt;GetGlobal("myvalue").GetInteger();<br />    <br />    // 调用Lua函数<br />    LuaFunction&lt;int&gt; luaPrint = state-&gt;GetGlobal("print");<br />    luaPrint("Hello World\n");<br />    <br />    // 让Lua调用C语言函数<br />    int add(int a, int b){ return a+b;}<br />    state-&gt;GetGlobals().RegisterDirect("add", add);<br />    state-&gt;DoString("print(add(3,4))");<br />    <br />    // 让Lua调用C++类成员函数<br />    class Test{public: int add(int a, int b){return a+b;}};<br />    Test test;<br />    state-&gt;GetGlobals().RegisterDirect("add", test, add);<br />    state-&gt;DoString("print(add(3,4))");<br />    <br />3. 在Lua脚本中使用C++类<br />    <br />    这个稍微有点小麻烦。不过，我包装了一个LuaPlusHelper.h的文件，它可以很轻松的完成这个工作。它的实现也很简单，大家可以从源码上来获得如何用纯LuaPlus实现同样的功能。<br />    不过，这里仍然有一个限制没有解决：不能使用虚成员函数。不过考虑到我们仅是在Lua调用一下C++函数，并不是要将C++完美的导入到Lua，这个限制完全可以接受。<br />    另外，类成员变量不能直接在Lua中访问，可以通过类成员函数来访问（比如SetValue/GetValue之类)。</p>
				<p> // 下面是一个简单的C++类:    <br /> class Logger<br /> {<br /> public:<br />  void LOGMEMBER(const char* message)<br />  {<br />   printf("In member function: %s\n", message);<br />  }<br /> <br />  Logger()<br />  {<br />   printf("Constructing(%p)...\n", this);<br />   v = 10;<br />  }<br />  virtual ~Logger()<br />  {<br />   printf("Destructing(%p)...\n", this);<br />  }<br /> <br />  Logger(int n)<br />  {<br />   printf(" -- Constructing[%d](%p)...\n", n, this);<br />  }<br />  Logger(Logger* logger)<br />  {<br />   printf(" -- Constructing[%p](%p)...\n", logger, this);<br />   logger-&gt;LOGMEMBER(" Call From Constructor\n");<br />  }<br />  int SetValue(int val)<br />  {<br />   v = val;<br />  }<br />  int GetValue()<br />  {<br />   return v;<br />  }<br /> public:<br />  int v;<br /> };</p>
				<p>    // 导入到Lua脚本：<br />    LuaClass&lt;Logger&gt;(state)<br /> .create("Logger") // 定义构造函数 Logger::Logger()<br /> .create&lt;int&gt;("Logger2")  // 定义构造函数 Logger::Logger(int)<br /> .create&lt;Logger*&gt;("Logger3") // 定义构造函数 Logger::Logger(Logger*)<br /> .destroy("Free")  // 定义析构函数 Logger::~Logger()<br /> .destroy("__gc")  // 定义析构函数 Logger::~Logger()<br /> .def("lm", &amp;Logger::LOGMEMBER)  // 定义成员函数 Logger::LOGMEMBER(const char*)<br /> .def("SetValue", &amp;Logger::SetValue)<br /> .def("GetValue", &amp;Logger::GetValue);<br /> <br />    // 在Lua中使用Logger类(1)：<br />    state-&gt;DoString(<br />        "l = Logger();"  // 调用构造函数 Logger::Logger()<br />        "l.lm('Hello World 1');"  // 调用成员函数 Logger::LOGMEMBER(const char*)<br />        "l.Free();"  // 调用析构函数 Logger::~Logger()<br />        );</p>
				<p>    // 在Lua中使用Logger类(2)：<br />    state-&gt;DoString(<br />        "m = Logger(10);" // 调用构造函数 Logger::Logger(int)<br />        "m.lm('Hello World 2');"  // 调用成员函数 Logger::LOGMEMBER(const char*)<br />        "n = Logger(m);" // 调用构造函数 Logger::Logger(Logger*)<br />        "n.lm('Hello World 3');"  // 调用成员函数 Logger::LOGMEMBER(const char*)<br />        "m.SetValue(11);"<br />        "print(m.GetValue());"<br />        "m,n = nil, nil;" // m,n 将由Lua的垃极回收来调用析构函数<br />        );</p>
				<p>4. 将一组C函数归类到Lua模块</p>
				<p>    //同上面一样，我采用LuaPlusHelper.h来简化：<br />    LuaModule(state, "mymodule")<br /> .def("add", add)<br /> .def("add2", test, add);<br /> <br />    state-&gt;DoString(<br />        "print(mymodule.add(3,4));"<br />        "print(mymodule.add2(3,4));"<br />        );</p>
				<p>5. 使用Lua的Table数据类型<br />    // 在Lua中创建Table<br />    LuaObject table = state-&gt;GetGlobals().CreateTable("mytable");<br />    table.SetInteger("m", 10);<br />    table.SetNumber("f", 1.99);<br />    table.SetString("s", "Hello World");<br />    table.SetWString("ch", L"你好");<br />    table.SetString(1, "What");<br />    <br />    // 相当于Lua中的：<br />    // mytable = {m=10, f=1.99, s="Hello World", ch=L"你好", "What"}<br />    <br />    // 也可以使用table作为key和value:<br />    state-&gt;GetGlobals().CreateTable("nexttable")<br />        .SetString(table, "Hello")<br />        .SetObject("obj", table);<br />    // 相当于Lua中的：<br />    // nexttable = {mytable="Hello", obj=mytable}<br />    <br />    //获得Table的内容：<br />    LuaObject t2 = state-&gt;GetGlobals("mytable");<br />    int m = t2.GetByName("m").GetInteger();<br />    <br />    LuaObject t3 = state-&gt;GetGlobals("nexttable");<br />    std::string str = t3.GetByObject(t2).GetString();<br />    <br />6  遍历Table</p>
				<p> LuaStateOwner state;<br /> state.DoString( "MyTable = { Hi = 5, Hello = 10, Yo = 6 }" );<br /> <br /> LuaObject obj = state.GetGlobals()[ "MyTable" ];<br /> for ( LuaTableIterator it( obj ); it; it.Next() )<br /> {<br />     const char* key = it.GetKey().GetString();<br />     int num = it.GetValue().GetInteger();<br /> }</p>
				<p>篇尾</p>
				<p>上面我只是简单的举一些例子来说明LuaPlus以及LuaPlusHelper的使用方法，具体文档请参见LuaPlus。</p>
				<p>需要下载LuaPlusHelper，请点这里：<br /><a href="http://www.d2-life.com/LBS/attachments/month_200509/06_zwo3LuaPlusHelper.zip" target="_blank">http://www.d2-life.com/LBS/attachments/month_200509/06_zwo3LuaPlusHelper.zip</a></p>
				<p>
				</p>
		</div>
<img src ="http://www.cppblog.com/mybios/aggbug/15337.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-18 09:46 <a href="http://www.cppblog.com/mybios/archive/2006/11/18/15337.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】使用 Lua 编写可嵌入式脚本</title><link>http://www.cppblog.com/mybios/archive/2006/11/18/15336.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 18 Nov 2006 01:39:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/18/15336.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15336.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/18/15336.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15336.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15336.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr valign="top">
								<td width="100%">
										<h1>使用 Lua 编写可嵌入式脚本</h1>
										<p id="subtitle">Lua 提供了高级抽象，却又没失去与硬件的关联</p>
										<img class="display-img" height="6" alt="" src="http://www.ibm.com/i/c.gif" width="1" />
								</td>
								<td class="no-print" width="192">
								</td>
						</tr>
				</tbody>
		</table>
		<table cellspacing="0" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr valign="top">
								<td width="10">
										<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
								</td>
								<td width="100%">
										<table class="no-print" cellspacing="0" cellpadding="0" width="160" align="right" border="0">
												<tbody>
														<tr>
																<td width="10">
																		<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" />
																</td>
																<td>
																		<table cellspacing="0" cellpadding="0" width="150" border="0">
																				<tbody>
																						<tr>
																								<td class="v14-header-1-small">
																								</td>
																						</tr>
																				</tbody>
																		</table>
																		<table class="v14-gray-table-border" cellspacing="0" cellpadding="0" border="0">
																				<tbody>
																						<tr>
																								<td class="no-padding" width="150">
																										<table cellspacing="0" cellpadding="0" width="143" border="0">
																												<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" />
																												<script language="JavaScript" type="text/javascript">
																														<!--
document.write('<tr valign="top"><td width="8"><img src="//www.ibm.com/i/c.gif" width="8" height="1" alt=""/></td><td width="16"><img src="//www.ibm.com/i/v14/icons/em.gif" height="16" width="16" vspace="3" alt="将此页作为电子邮件发送" /></td><td width="122"><p><a class="smallplainlink" href="javascript:document.email.submit();"><b>将此页作为电子邮件发送</b></a></p></td></tr>');
//-->
																												</script>
																												<tbody>
																														<tr valign="top">
																																<td width="8">
																																		<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" />
																																</td>
																																<td width="16">
																																</td>
																																<td width="122">
																																</td>
																														</tr>
																														<noscript>
																																<tr valign="top">
																																		<td width="8">
																																				<img height="1" alt="" src="//www.ibm.com/i/c.gif" width="8" />
																																		</td>
																																		<td width="16">
																																				<img height="16" alt="" src="//www.ibm.com/i/c.gif" width="16" />
																																		</td>
																																		<td class="small" width="122">
																																				<p>
																																						<span class="ast">未显示需要 JavaScript 的文档选项</span>
																																				</p>
																																		</td>
																																</tr>
																														</noscript>
																												</tbody>
																										</table>
																								</td>
																						</tr>
																				</tbody>
																		</table>
																		<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
																		<!-- 03/20/06 updated by gretchen -->
																		<br />
																		<table cellspacing="0" cellpadding="0" width="150" border="0">
																				<tbody>
																						<tr>
																								<td class="v14-header-2-small">
																								</td>
																						</tr>
																				</tbody>
																		</table>
																		<table class="v14-gray-table-border" cellspacing="0" cellpadding="0" border="0">
																				<tbody>
																						<tr>
																								<td class="no-padding" width="150">
																										<table cellspacing="0" cellpadding="0" width="143" border="0">
																												<tbody>
																														<tr valign="top">
																																<td width="8">
																																		<img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="8" />
																																</td>
																																<td>
																																</td>
																																<td width="125">
																																</td>
																														</tr>
																												</tbody>
																										</table>
																								</td>
																						</tr>
																				</tbody>
																		</table>
																		<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
																		<br />
																</td>
														</tr>
												</tbody>
										</table>
										<p>级别: 初级</p>
										<p>
												<a href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#author">
														<font color="#996699">Martin Streicher </font>
												</a>(<a href="mailto:martin.streicher@linux-mag.com?subject=使用 Lua 编写可嵌入式脚本"><font color="#5c81a7">martin.streicher@linux-mag.com</font></a>), 首席编辑, Linux Magazine<br /></p>
										<p>2006 年 6 月 12 日</p>
										<blockquote>虽然编译性编程语言和脚本语言各自具有自己独特的优点，但是如果我们使用这两种类型的语言来编写大型的应用程序会是什么样子呢？Lua 是一种嵌入式脚本语言，它非常小，速度很快，功能却非常强大。在创建其他配置文件或资源格式（以及与之对应的解析器）之前，请尝试一下 Lua。</blockquote>
										<!--START RESERVED FOR FUTURE USE INCLUDE FILES-->
										<!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters -->
										<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->
										<p>尽管诸如 Perl、Python、PHP 和 Ruby 之类的解释性编程语言日益被 Web 应用程序广泛地采纳 —— 它们已经长期用来实现自动化系统管理任务 —— 但是诸如 C、C++ 之类的编译性编程语言依然是必需的。编译性编程语言的性能是脚本语言所无法企及的（只有手工调优的汇编程序的性能才能超过它），有些软件 —— 包括操作系统和设备驱动程序 —— 只能使用编译代码来高效地实现。实际上，当软件和硬件需要进行无缝地连接操作时，程序员本能地就会选择 C 编译器：C 非常基础，距离 “原始金属材料非常近” —— 即可以操作硬件的很多特性 —— 并且 C 的表现力非常强大，可以提供高级编程结构，例如结构、循环、命名变量和作用域。</p>
										<p>然而，脚本语言也有自己独特的优点。例如，当某种语言的解释器被成功移植到一种平台上以后，使用这种语言编写的大量脚本就可以不加任何修改在这种新平台上运行 —— 它们没有诸如系统特定的函数库之类的依赖限制。（我们可以考虑一下 Microsoft® Windows® 操作系统上的许多 DLL 文件和 UNIX® 及 Linux® 上的很多 libcs）。另外，脚本语言通常都还会提供高级编程构造和便利的操作，程序员可以使用这些功能来提高生产效率和灵活性。另外，使用解释语言来编程的程序员工作的速度更快，因为这不需要编译和链接的步骤。C 及其类似语言中的 “编码、编译、链接、运行” 周期缩减成了更为紧凑的 “编写脚本、运行”。</p>
										<p>
												<a name="luanovel">
														<span class="atitle">
																<font face="Arial" size="4">Lua 新特性</font>
														</span>
												</a>
										</p>
										<p>与其他脚本语言一样，Lua 也有自己的一些特性：</p>
										<ul>
												<li>
														<b>Lua 类型。</b>在 Lua 中，值可以有类型，但是变量的类型都是动态决定的。<i>nil、布尔型、数字</i> 和 <i>字符串</i> 类型的工作方式与我们期望的一样。 
<ul><li>Nil 是值为 <code>nil</code> 的一种特殊类型，用来表示没有值。 
</li><li>布尔型的值可以是 <code>true</code> 和 <code>false</code> 常量。（<code>Nil</code> 也可以表示 false，任何非 <code>nil</code> 的值都表示 true。） 
</li><li>Lua 中所有的数字都是双精度的（不过我们可以非常简便地编写一些代码来实现其他数字类型）。 
</li><li>字符串是定长字符数组。（因此，要在一个字符串后面附加上字符，必须对其进行拷贝。） </li></ul></li>
												<li>
														<i>表、函数</i> 和<i>线程</i> 类型都是引用。每个都可以赋值给一个变量，作为参数传递，或作为返回值从函数中返回。例如，下面是一个存储函数的例子：<br /><br /><table cellspacing="0" cellpadding="5" width="80%" bgcolor="#eeeeee" border="1"><tbody><tr><td><code><pre class="section">-- 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
</pre></code></td></tr></tbody></table><br /></li>
												<li>
														<b>Lua 线程。</b>线程是通过调用内嵌函数 <code>coroutine.create(f)</code> 创建的一个<i>协同例程 (co-routine)</i>，其中 <i>f</i> 是一个 Lua 函数。线程不会在创建时启动；相反，它是在创建之后使用 <code>coroutine.resume(t)</code> 启动的，其中 <i>t</i> 就是一个线程。每个协同例程都必须使用 <code>coroutine.yield()</code> 偶尔获得其他协同例程的处理器。 
</li>
												<li>
														<b>赋值语句。</b>Lua 允许使用多种赋值语句，可以先对表达式进行求值，然后再进行赋值。例如，下面的语句：<br /><br /><table cellspacing="0" cellpadding="5" width="80%" bgcolor="#eeeeee" border="1"><tbody><tr><td><code><pre class="section">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)
</pre></code></td></tr></tbody></table><br />会生成 <code>4 7 5 nil nil</code>。如果变量列表的个数大于值列表的个数，那么多出的变量都被赋值为 <code>nil</code>；因此，<code>b</code> 就是 nil。如果值的个数多于变量的个数，那么多出的值部分就会简单地丢弃。在 Lua 中，变量名是大小写敏感的，这可以解释为什么 <code>I</code> 的值是 nil。 
</li>
												<li>
														<b>块（Chunk）。</b>
														<i>块</i> 可以是任何 Lua 语句序列。块可以保存到文件中，或者保存到 Lua 程序中的字符串中。每个块都是作为一个匿名函数体来执行的。因此，块可以定义局部变量和返回值。 
</li>
												<li>
														<b>更酷的东西。</b>Lua 具有一个标记-清理垃圾收集器。在 Lua 5.1 中，垃圾收集器是以增量方式工作的。Lua 具有完整的词法闭包（这与 Scheme 类似，而与 Python 不同）。Lua 具有可靠的尾部调用语义（同样，这也与 Scheme 类似，而与 Python 不同）。 </li>
										</ul>
										<p>在 <i>Programming in Lua</i> 和 Lua-users wiki （链接请参见后面的 <a href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#resources"><font color="#996699">参考资料</font></a> 部分）中可以找到更多 Lua 代码的例子。</p>
										<p>在所有的工程任务中，要在编译性语言和解释性语言之间作出选择，就意味着要在这种环境中对每种语言的优缺点、权重和折中进行评测，并接受所带来的风险。</p>
										<br />
										<table cellspacing="0" cellpadding="0" width="100%" border="0">
												<tbody>
														<tr>
																<td>
																		<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
																		<br />
																		<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
																</td>
														</tr>
												</tbody>
										</table>
										<table class="no-print" cellspacing="0" cellpadding="0" align="right">
												<tbody>
														<tr align="right">
																<td>
																		<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
																		<br />
																		<table cellspacing="0" cellpadding="0" border="0">
																				<tbody>
																						<tr>
																								<td valign="center">
																										<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																										<br />
																								</td>
																								<td valign="top" align="right">
																										<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#main">
																												<b>
																														<font color="#996699">回页首</font>
																												</b>
																										</a>
																								</td>
																						</tr>
																				</tbody>
																		</table>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<br />
										<p>
												<a name="N100ED">
														<span class="atitle">
																<font face="Arial" size="4">在两个世界之间最好地进行混合</font>
														</span>
												</a>
										</p>
										<p>如果您希望充分利用这两个世界的优点，应该怎样办呢，是选择最好的性能还是选择高级强大的抽象？更进一步说，如果我们希望对处理器密集且依赖于系统的算法和函数以及与系统无关且很容易根据需要而进行修改的单独逻辑进行优化，那又当如何呢？</p>
										<p>对高性能代码和高级编程的需要进行平衡是 Lua（一种可嵌入式脚本语言）要解决的问题。在需要时我们可以使用编译后的代码来实现底层的功能，然后调用 Lua 脚本来操作复杂的数据。由于 Lua 脚本是与编译代码独立的，因此我们可以单独修改这些脚本。使用 Lua，开发周期就非常类似于 “编码、编译、运行、编写脚本、编写脚本、编写脚本 ...”。</p>
										<p>例如，Lua Web 站点 “使用” 页面（请参见 <a href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#resources"><font color="#996699">参考资料</font></a>）列出了主流市场上的几个计算机游戏，包括 <i>World of Warcraft</i> 和（家用版的）<i>Defender</i>，它们集成 Lua 来实现很多东西，从用户界面到敌人的人工智能都可以。Lua 的其他应用程序包括流行的 Linux 软件更新工具 apt-rpm 的扩展机制，还有 “Crazy Ivan” Robocup 2000 冠军联赛的控制逻辑。这个页面上的很多推荐感言都对 Lua 的小巧与杰出性能赞不绝口。</p>
										<br />
										<table cellspacing="0" cellpadding="0" width="100%" border="0">
												<tbody>
														<tr>
																<td>
																		<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
																		<br />
																		<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
																</td>
														</tr>
												</tbody>
										</table>
										<table class="no-print" cellspacing="0" cellpadding="0" align="right">
												<tbody>
														<tr align="right">
																<td>
																		<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
																		<br />
																		<table cellspacing="0" cellpadding="0" border="0">
																				<tbody>
																						<tr>
																								<td valign="center">
																										<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																										<br />
																								</td>
																								<td valign="top" align="right">
																										<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#main">
																												<b>
																														<font color="#996699">回页首</font>
																												</b>
																										</a>
																								</td>
																						</tr>
																				</tbody>
																		</table>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<br />
										<p>
												<a name="N10106">
														<span class="atitle">
																<font face="Arial" size="4">开始使用 Lua</font>
														</span>
												</a>
										</p>
										<p>Lua 5.0.2 版本是撰写本文时的最新版本，不过最近刚刚发布了 5.1 版本。您可以从 lua.org 上下载 Lua 的源代码，在 Lua-users wiki（链接请参见 <a href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#resources"><font color="#996699">参考资料</font></a>）上可以找到预先编译好的二进制文件。完整的 Lua 5.0.2 核心文件中包括了标准库和 Lua 编译器，不过只有 200KB 大小。</p>
										<p>如果您使用的是 Debian Linux，那么可以以超级用户的身份运行下面的命令来快速安装 Lua 5.0：</p>
										<table cellspacing="0" cellpadding="5" width="80%" bgcolor="#eeeeee" border="1">
												<tbody>
														<tr>
																<td>
																		<code>
																				<pre class="section"># apt-get install lua50
</pre>
																		</code>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<p>本文中给出的例子都是在 Debian Linux Sarge 上运行的，使用的是 Lua 5.0.2 和 2.4.27-2-686 版本的 Linux 内核。</p>
										<p>在系统上安装好 Lua 之后，我们可以首先来试用一下单独的 Lua 解释器。（所有的 Lua 应用程序必须要嵌入到宿主应用程序中。解释器只是一种特殊类型的宿主，对于开发和调试工作来说非常有用。）创建一个名为 factorial.lua 的文件，然后输入下面的代码：</p>
										<table cellspacing="0" cellpadding="5" width="80%" bgcolor="#eeeeee" border="1">
												<tbody>
														<tr>
																<td>
																		<code>
																				<pre class="section">-- 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))
</pre>
																		</code>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<p>factorial.lua 中的代码 —— 更确切地说是任何 Lua 语句序列 —— 都称为一个<i>块</i>，这在上面的 <a href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#luanovel"><font color="#996699">Lua 特性</font></a> 中已经进行了介绍。要执行刚才创建的代码块，请运行命令 <code>lua factorial.lua</code>：</p>
										<table cellspacing="0" cellpadding="5" width="80%" bgcolor="#eeeeee" border="1">
												<tbody>
														<tr>
																<td>
																		<code>
																				<pre class="section">$ lua factorial.lua
enter a number:
10
3628800
</pre>
																		</code>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<p>或者像在其他解释性语言中一样，我们可以在代码顶部添加一行 “标识符”（<code>#!</code>），使这个脚本变成可执行的，然后像单独命令一样来运行这个文件：</p>
										<table cellspacing="0" cellpadding="5" width="80%" bgcolor="#eeeeee" border="1">
												<tbody>
														<tr>
																<td>
																		<code>
																				<pre class="section">$ (echo '#! /usr/bin/lua'; cat factorial.lua) &gt; factorial 
$ chmod u+x factorial
$ ./factorial
enter a number:
4
24
</pre>
																		</code>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<br />
										<table cellspacing="0" cellpadding="0" width="100%" border="0">
												<tbody>
														<tr>
																<td>
																		<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
																		<br />
																		<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
																</td>
														</tr>
												</tbody>
										</table>
										<table class="no-print" cellspacing="0" cellpadding="0" align="right">
												<tbody>
														<tr align="right">
																<td>
																		<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
																		<br />
																		<table cellspacing="0" cellpadding="0" border="0">
																				<tbody>
																						<tr>
																								<td valign="center">
																										<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																										<br />
																								</td>
																								<td valign="top" align="right">
																										<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#main">
																												<b>
																														<font color="#996699">回页首</font>
																												</b>
																										</a>
																								</td>
																						</tr>
																				</tbody>
																		</table>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<br />
										<p>
												<a name="N1015A">
														<span class="atitle">
																<font face="Arial" size="4">Lua 语言</font>
														</span>
												</a>
										</p>
										<p>Lua 具有现代脚本语言中的很多便利：作用域，控制结构，迭代器，以及一组用来处理字符串、产生及收集数据和执行数学计算操作的标准库。在 <i>Lua 5.0 Reference Manual</i> 中有对 Lua 语言的完整介绍（请参见 <a href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#resources"><font color="#996699">参考资料</font></a>）。</p>
										<p>在 Lua 中，只有<i>值</i> 具有类型，而变量的类型是动态决定的。Lua 中的基本类型（值）有 8 种： <i>nil，布尔型，数字，字符串，函数，线程，表</i> 以及 <i>用户数据</i>。前 6 种类型基本上是自描述的（例外情况请参见上面的 <a href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#luanovel"><font color="#996699">Lua 特性</font></a> 一节）；最后两个需要一点解释。</p>
										<p>
												<a name="N1017A">
														<span class="smalltitle">
																<strong>
																		<font face="Arial">Lua 表</font>
																</strong>
														</span>
												</a>
										</p>
										<p>在 Lua 中，表是用来保存所有数据的结构。实际上，表是 Lua 中<i>惟一的</i> 数据结构。我们可以将表作为数组、字典（也称为<i>散列</i> 或<i>联合数组</i>）、树、记录，等等。</p>
										<p>与其他编程语言不同，Lua 表的概念不需要是异构的：表可以包含任何类型的组合，也可以包含类数组元素和类字典元素的混合体。另外，<i>任何</i> Lua 值 —— 包括函数或其他表 —— 都可以用作字典元素的键值。</p>
										<p>要对表进行浏览，请启动 Lua 解释器，并输入清单 1 中的<b>黑体</b>显示的代码。</p>
										<br />
										<a name="Listing1">
												<b>清单 1. 体验 Lua 表</b>
										</a>
										<br />
										<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
												<tbody>
														<tr>
																<td>
																		<code>
																				<pre class="section">$ lua
&gt; -- create an empty table and add some elements
&gt; t1 = {}
&gt; t1[1] = "moustache"
&gt; t1[2] = 3
&gt; t1["brothers"] = true

&gt; -- more commonly, create the table and define elements
&gt; all at once
&gt; t2 = {[1] = "groucho", [3] = "chico", [5] = "harpo"}
&gt; t3 = {[t1[1]] = t2[1], accent = t2[3], horn = t2[5]}
&gt; t4 = {}
&gt; t4[t3] = "the marx brothers"
&gt; t5 = {characters = t2, marks = t3}
&gt; t6 = {["a night at the opera"] = "classic"}

&gt; -- make a reference and a string
&gt; i = t3
&gt; s = "a night at the opera"

&gt; -- indices can be any Lua value
&gt; print(t1[1], t4[t3], t6[s])
moustache   the marx brothers classic

&gt; -- the phrase table.string is the same as table["string"]
&gt; print(t3.horn, t3["horn"])
harpo   harpo

&gt; -- indices can also be "multi-dimensional"
&gt; print (t5["marks"]["horn"], t5.marks.horn)
harpo   harpo

&gt; -- i points to the same table as t3
&gt; = t4[i]
the marx brothers

&gt; -- non-existent indices return nil values
&gt; print(t1[2], t2[2], t5.films)
nil     nil     nil

&gt;  -- even a function can be a key 
&gt; t = {}
&gt; function t.add(i,j)
&gt;&gt; return(i+j)
&gt;&gt; end
&gt; print(t.add(1,2))
3
&gt; print(t['add'](1,2))
3
&gt;  -- and another variation of a function as a key 
&gt; t = {}
&gt; function v(x)
&gt;&gt; print(x)
&gt;&gt; end
&gt; t[v] = "The Big Store"
&gt; for key,value in t do key(value) end
The Big Store
</pre>
																		</code>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<p>正如我们可能期望的一样，Lua 还提供了很多迭代器函数来对表进行处理。全局变量 <code>table</code> 提供了这些函数（是的，Lua 包就是表）。有些函数，例如 <code>table.foreachi()</code>，会期望一个从 1（数字 1）开始的连续整数范围：</p>
										<table cellspacing="0" cellpadding="5" width="80%" bgcolor="#eeeeee" border="1">
												<tbody>
														<tr>
																<td>
																		<code>
																				<pre class="section">&gt; table.foreachi(t1, print)
1 moustache
2 3
</pre>
																		</code>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<p>另外一些函数，例如 <code>table.foreach()</code>，会对整个表进行迭代：</p>
										<table cellspacing="0" cellpadding="5" width="80%" bgcolor="#eeeeee" border="1">
												<tbody>
														<tr>
																<td>
																		<code>
																				<pre class="section">&gt; table.foreach(t2,print)
1       groucho
3       chico
5       harpo
&gt; table.foreach(t1,print)
1       moustache
2       3
brothers        true
</pre>
																		</code>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<p>尽管有些迭代器对整数索引进行了优化，但是所有迭代器都只简单地处理 (key, value) 对。</p>
										<p>现在我们可以创建一个表 <code>t</code>，其元素是 <code>{2, 4, 6, language="Lua", version="5", 8, 10, 12, web="www.lua.org"}</code>，然后运行 <code>table.foreach(t, print) </code>和 <code>table.foreachi(t, print)</code>。</p>
										<p>
												<a name="N10233">
														<span class="smalltitle">
																<strong>
																		<font face="Arial">用户数据</font>
																</strong>
														</span>
												</a>
										</p>
										<p>由于 Lua 是为了嵌入到使用另外一种语言（例如 C 或 C++）编写的宿主应用程序中，并与宿主应用程序协同工作，因此数据可以在 C 环境和 Lua 之间进行共享。正如 <i>Lua 5.0 Reference Manual</i> 所说，<code>userdata</code> 类型允许我们在 Lua 变量中保存任意的 C 数据。我们可以认为 <code>userdata</code> 就是一个字节数组 —— 字节可以表示指针、结构或宿主应用程序中的文件。</p>
										<p>用户数据的内容源自于 C，因此在 Lua 中不能对其进行修改。当然，由于用户数据源自于 C，因此在 Lua 中也没有对用户数据预定义操作。不过我们可以使用另外一种 Lua 机制来创建对 <code>userdata</code> 进行处理的操作，这种机制称为 <i>元表（metatable）。</i></p>
										<p>
												<a name="N10251">
														<span class="smalltitle">
																<strong>
																		<font face="Arial">元表</font>
																</strong>
														</span>
												</a>
										</p>
										<p>由于表和用户数据都非常灵活，因此 Lua 允许我们重载这两种类型的数据的操作（不能重载其他 6 种类型）。<i>元表</i> 是一个（普通的）Lua 表，它将标准操作映射成我们提供的函数。元表的键值称为<i>事件</i>；值（换而言之就是函数）称为<i>元方法</i>。</p>
										<p>函数 <code>setmetatable()</code> 和 <code>getmetatable()</code> 分别对对象的元表进行修改和查询。每个表和 <code>userdada</code> 对象都可以具有自己的元表。</p>
										<p>例如，添加操作对应的事件是 <code>__add</code>。我们可以推断这段代码所做的事情么？</p>
										<table cellspacing="0" cellpadding="5" width="80%" bgcolor="#eeeeee" border="1">
												<tbody>
														<tr>
																<td>
																		<code>
																				<pre class="section">-- 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 )
</pre>
																		</code>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<p>这段代码会产生下面的文本：</p>
										<table cellspacing="0" cellpadding="5" width="80%" bgcolor="#eeeeee" border="1">
												<tbody>
														<tr>
																<td>
																		<code>
																				<pre class="section">Hello There World!
</pre>
																		</code>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<p>函数 <code>String()</code> 接收一个字符串 <code>string</code>，将其封装到一个表（<code>{value = s or ''}</code>）中，并将元表 <code>mt</code> 赋值给这个表。函数 <code>mt.__add()</code> 是一个元方法，它将字符串 <code>b</code> 添加到在 <code>a.value</code> 中找到的字符串后面 <code>b</code> 次。这行代码 <code>print((s + ' There ' + ' World!').value )</code> 调用这个元方法两次。</p>
										<p>
												<code>__index</code> 是另外一个事件。<code>__index</code> 的元方法每当表中不存在键值时就会被调用。下面是一个例子，它记住 (memoize) 函数的值：</p>
										<table cellspacing="0" cellpadding="5" width="80%" bgcolor="#eeeeee" border="1">
												<tbody>
														<tr>
																<td>
																		<code>
																				<pre class="section">-- 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
)
</pre>
																		</code>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<p>将这段代码放到 Lua 解释器中，然后输入 <code>print(color[1], color[2], color[1])</code>。您将会看到类似于 <code>blue black blue</code> 的内容。</p>
										<p>这段代码接收一个键值 <code>node</code>，查找 node 指定的颜色。如果这种颜色不存在，代码就会给 <code>node</code> 赋一个新的随机选择的颜色。否则，就返回赋给 node 的颜色。在前一种情况中，<code>__index</code> 元方法被执行一次以分配一个颜色。后一种情况比较简单，所执行的是快速散列查找。</p>
										<p>Lua 语言提供了很多其他功能强大的特性，所有这些特性都有很好的文档进行介绍。在碰到问题或希望与专家进行交谈时，请连接 Lua Users Chat Room IRC Channel（请参见 <a href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#resources"><font color="#996699">参考资料</font></a>）获得非常热心的支持。</p>
										<br />
										<table cellspacing="0" cellpadding="0" width="100%" border="0">
												<tbody>
														<tr>
																<td>
																		<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
																		<br />
																		<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
																</td>
														</tr>
												</tbody>
										</table>
										<table class="no-print" cellspacing="0" cellpadding="0" align="right">
												<tbody>
														<tr align="right">
																<td>
																		<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
																		<br />
																		<table cellspacing="0" cellpadding="0" border="0">
																				<tbody>
																						<tr>
																								<td valign="center">
																										<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																										<br />
																								</td>
																								<td valign="top" align="right">
																										<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#main">
																												<b>
																														<font color="#996699">回页首</font>
																												</b>
																										</a>
																								</td>
																						</tr>
																				</tbody>
																		</table>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<br />
										<p>
												<a name="N102DF">
														<span class="atitle">
																<font face="Arial" size="4">嵌入和扩展</font>
														</span>
												</a>
										</p>
										<p>除了语法简单并且具有功能强大的表结构之外，Lua 的强大功能使其可以与宿主语言混合使用。由于 Lua 与宿主语言的关系非常密切，因此 Lua 脚本可以对宿主语言的功能进行扩充。但是这种融合是双赢的：宿主语言同时也可以对 Lua 进行扩充。举例来说，C 函数可以调用 Lua 函数，反之亦然。</p>
										<p>Lua 与宿主语言之间的这种共生关系的核心是宿主语言是一个<i>虚拟堆栈</i>。虚拟堆栈与实际堆栈类似，是一种后进先出（LIFO）的数据结构，可以用来临时存储函数参数和函数结果。要从 Lua 中调用宿主语言的函数（反之亦然），调用者会将一些值压入堆栈中，并调用目标函数；被调用的函数会弹出这些参数（当然要对类型和每个参数的值进行验证），对数据进行处理，然后将结果放入堆栈中。当控制返回给调用程序时，调用程序就可以从堆栈中提取出返回值。</p>
										<p>实际上在 Lua 中使用的所有的 C 应用程序编程接口（API）都是通过堆栈来进行操作的。堆栈可以保存 Lua 的值，不过值的类型必须是调用程序和被调用者都知道的，特别是向堆栈中压入的值和从堆栈中弹出的值更是如此（例如 <code>lua_pushnil()</code> 和 <code>lua_pushnumber()</code>。</p>
										<p>清单 2 给出了一个简单的 C 程序（节选自 <a href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#resources"><font color="#996699">参考资料</font></a> 中 <i>Programming in Lua</i> 一书的第 24 章），它实现了一个很小但却功能完善的 Lua 解释器。</p>
										<br />
										<a name="Listing2">
												<b>清单 2. 一个简单的 Lua 解释器</b>
										</a>
										<br />
										<table cellspacing="0" cellpadding="5" width="100%" bgcolor="#eeeeee" border="1">
												<tbody>
														<tr>
																<td>
																		<code>
																				<pre class="section"> 1 #include &lt;stdio.h&gt;
 2 #include &lt;lua.h&gt;
 3 #include &lt;lauxlib.h&gt;
 4 #include &lt;lualib.h&gt;
 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 }
</pre>
																		</code>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<p>第 2 行到第 4 行包括了 Lua 的标准函数，几个在所有 Lua 库中都会使用的方便函数以及用来打开库的函数。第 9 行创建了一个 Lua <i>状态</i>。所有的状态最初都是空的；我们可以使用 <code>luaopen_...()</code> 将函数库添加到状态中，如第 10 行到第 14 行所示。</p>
										<p>第 17 行和 <code>luaL_loadbuffer()</code> 会从 <code>stdin</code> 中以块的形式接收输入，并对其进行编译，然后将其放入虚拟堆栈中。第 18 行从堆栈中弹出数据并执行之。如果在执行时出现了错误，就向堆栈中压入一个 Lua 字符串。第 20 行访问栈顶（栈顶的索引为 <code>-1</code>）作为 Lua 字符串，打印消息，然后从堆栈中删除该值。</p>
										<p>使用 C API，我们的应用程序也可以进入 Lua 状态来提取信息。下面的代码片段从 Lua 状态中提取两个全局变量：</p>
										<table cellspacing="0" cellpadding="5" width="80%" bgcolor="#eeeeee" border="1">
												<tbody>
														<tr>
																<td>
																		<code>
																				<pre class="section">..
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);
..
</pre>
																		</code>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<p>请再次注意传输是通过堆栈进行的。从 C 中调用任何 Lua 函数与这段代码类似：使用 <code>lua_getglobal()</code> 来获得函数，将参数压入堆栈，调用 <code>lua_pcall()</code>，然后处理结果。如果 Lua 函数返回 <i>n</i> 个值，那么第一个值的位置在堆栈的 <i>-n</i> 处，最后一个值在堆栈中的位置是 -1。</p>
										<p>反之，在 Lua 中调用 C 函数也与之类似。如果您的操作系统支持动态加载，那么 Lua 可以根据需要来动态加载并调用函数。（在必须使用静态加载的操作系统中，可以对 Lua 引擎进行扩充，此时调用 C 函数时需要重新编译 Lua。）</p>
										<br />
										<table cellspacing="0" cellpadding="0" width="100%" border="0">
												<tbody>
														<tr>
																<td>
																		<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
																		<br />
																		<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
																</td>
														</tr>
												</tbody>
										</table>
										<table class="no-print" cellspacing="0" cellpadding="0" align="right">
												<tbody>
														<tr align="right">
																<td>
																		<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
																		<br />
																		<table cellspacing="0" cellpadding="0" border="0">
																				<tbody>
																						<tr>
																								<td valign="center">
																										<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																										<br />
																								</td>
																								<td valign="top" align="right">
																										<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#main">
																												<b>
																														<font color="#996699">回页首</font>
																												</b>
																										</a>
																								</td>
																						</tr>
																				</tbody>
																		</table>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<br />
										<p>
												<a name="N10341">
														<span class="atitle">
																<font face="Arial" size="4">结束语</font>
														</span>
												</a>
										</p>
										<p>Lua 是一种学习起来容易得难以置信的语言，但是它简单的语法却掩饰不了其强大的功能：这种语言支持对象（这与 Perl 类似），元表使表类型具有相当程度的可伸展性，C API 允许我们在脚本和宿主语言之间进行更好的集成和扩充。Lua 可以在 C、C++、C#、Java™ 和 Python 语言中使用。</p>
										<p>在创建另外一个配置文件或资源格式（以及相应的处理程序）之前，请尝试一下 Lua。Lua 语言及其社区非常健壮，具有创新精神，随时准备好提供帮助。</p>
										<br />
										<table cellspacing="0" cellpadding="0" width="100%" border="0">
												<tbody>
														<tr>
																<td>
																		<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
																		<br />
																		<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
																</td>
														</tr>
												</tbody>
										</table>
										<table class="no-print" cellspacing="0" cellpadding="0" align="right">
												<tbody>
														<tr align="right">
																<td>
																		<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
																		<br />
																		<table cellspacing="0" cellpadding="0" border="0">
																				<tbody>
																						<tr>
																								<td valign="center">
																										<img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" />
																										<br />
																								</td>
																								<td valign="top" align="right">
																										<a class="fbox" href="http://www-128.ibm.com/developerworks/cn/linux/l-lua.html#main">
																												<b>
																														<font color="#996699">回页首</font>
																												</b>
																										</a>
																								</td>
																						</tr>
																				</tbody>
																		</table>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<br />
										<p>
												<a name="resources">
														<span class="atitle">
																<font face="Arial" size="4">参考资料 </font>
														</span>
												</a>
										</p>
										<b>学习</b>
										<br />
										<ul>
												<li>您可以参阅本文在 developerWorks 全球站点上的 <a href="http://www.ibm.com/developerworks/linux/library/l-lua.html" target="_blank"><font color="#5c81a7">英文原文</font></a>。<br /><br /></li>
												<li>
														<a href="http://www.lua.org/manual/5.0">
																<i>
																		<font color="#5c81a7">Reference manual for Lua 5.0</font>
																</i>
														</a>介绍了 Lua 语言的完整知识。 <br /><br /></li>
												<li>Roberto Ierusalimschy 所著的 <a href="http://www.lua.org/pil"><i><font color="#5c81a7">Programming in Lua</font></i></a>（Roberto Ierusalimschy，2003 年）是学习如何使用 Lua 有效地进行编码的非常有用的资源。 <br /><br /></li>
												<li>请参阅 Lua-users wiki 中的 <a href="http://lua-users.org/wiki/TutorialDirectory"><font color="#5c81a7">library of Lua 教程</font></a>，学习如何使用 Lua 的特性。 <br /><br /></li>
												<li>请参阅 <a href="http://www.lua.org/uses.html"><font color="#5c81a7">使用 Lua 的项目列表</font></a>。 <br /><br /></li>
												<li>在 <a href="http://www.ibm.com/developerworks/cn/linux/"><font color="#5c81a7">developerWorks Linux 专区</font></a> 可以找到为 Linux 开发人员准备的更多资源。 <br /><br /></li>
												<li>随时关注 <a href="http://www.ibm.com/developerworks/offers/techbriefings/?S_TACT=105AGX03&amp;S_CMP=art"><font color="#5c81a7">developerWorks 技术事件和网络广播</font></a>。 </li>
										</ul>
										<br />
										<b>获得产品和技术</b>
										<br />
										<ul>
												<li>下载 <a href="http://www.lua.org/ftp/lua-5.0.2.tar.gz"><font color="#5c81a7">Lua 5.0.2</font></a> 或 <a href="http://www.lua.org/ftp/lua-5.1.tar.gz"><font color="#5c81a7">Lua 5.1</font></a> 源代码，从头开始编译 Lua。 <br /><br /></li>
												<li>在 <a href="http://lua-users.org/wiki/LuaBinaries"><font color="#5c81a7">Lua-users wiki</font></a> 上，浏览很多预先构建的、可安装的 Lua 二进制文件。 <br /><br /></li>
												<li>在 <a href="http://www.luaforge.net/"><font color="#5c81a7">LuaForge</font></a> 上可以找到大量的代码库，包括很多语言绑定和专门的计算库。 <br /><br /></li>
												<li>
														<a href="http://www.ibm.com/developerworks/offers/sek/?S_TACT=105AGX03&amp;S_CMP=art">
																<font color="#5c81a7">订购免费的 SEK for Linux</font>
														</a>，这有两张 DVD，包括最新的 IBM for Linux 试用软件，包括 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere®。 <br /><br /></li>
												<li>在您的下一个开发项目中采用 <a href="http://www.ibm.com/developerworks/downloads/?S_TACT=105AGX03"><font color="#5c81a7">IBM 试用软件</font></a>，这可以从 developerWorks 直接下载。 <br /><br /></li>
										</ul>
										<br />
										<b>讨论</b>
										<br />
										<ul>
												<li>通过参与 <a href="http://www.ibm.com/developerworks/blogs/"><font color="#5c81a7">developerWorks blogs</font></a> 加入 developerWorks 社区。 <br /><br /></li>
										</ul>
										<br />
										<table cellspacing="0" cellpadding="0" width="100%" border="0">
												<tbody>
														<tr>
																<td>
																		<img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" />
																		<br />
																		<img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" />
																</td>
														</tr>
												</tbody>
										</table>
										<table class="no-print" cellspacing="0" cellpadding="0" align="right">
												<tbody>
														<tr align="right">
																<td>
																		<img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
																		<br />
																		<table cellspacing="0" cellpadding="0" border="0">
																				<tbody>
																						<tr>
																								<td valign="center">
																										<br />
																								</td>
																								<td valign="top" align="right">
																								</td>
																						</tr>
																				</tbody>
																		</table>
																</td>
														</tr>
												</tbody>
										</table>
										<br />
										<br />
										<p>
												<a name="author">
														<span class="atitle">
																<font face="Arial" size="4">关于作者</font>
														</span>
												</a>
										</p>
										<table cellspacing="0" cellpadding="0" width="100%" border="0">
												<tbody>
														<tr>
																<td colspan="3">
																		<font face="Arial" size="4">
																				<img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="100%" />
																		</font>
																</td>
														</tr>
														<tr valign="top" align="left">
																<td>
																		<p>
																				<font face="Arial" size="4">
																				</font>
																		</p>
																</td>
																<td>
																		<font face="Arial" size="4">
																				<img height="5" alt="" src="http://www.ibm.com/i/c.gif" width="4" />
																		</font>
																</td>
																<td width="100%">
																		<p>Martin Streicher 是 <i>Linux Magazine</i> 的首席编辑。他在普渡大学获得了计算机硕士学位，自 1982 年以来，就一直在使用 Pascal、C、Perl、Java 以及（最近使用的）Ruby 编程语言编写类 Unix 系统。</p>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.cppblog.com/mybios/aggbug/15336.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-18 09:39 <a href="http://www.cppblog.com/mybios/archive/2006/11/18/15336.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】Lua 5.0 参考手册 </title><link>http://www.cppblog.com/mybios/archive/2006/11/18/15335.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 18 Nov 2006 01:37:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/18/15335.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15335.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/18/15335.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15335.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15335.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Lua 5.0 参考手册 		作者： Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes 																		Copyright © 2003 Tecgraf, PUC-Rio. All rights reserved. 				译者：ShiningRay Nicholas...&nbsp;&nbsp;<a href='http://www.cppblog.com/mybios/archive/2006/11/18/15335.html'>阅读全文</a><img src ="http://www.cppblog.com/mybios/aggbug/15335.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-18 09:37 <a href="http://www.cppblog.com/mybios/archive/2006/11/18/15335.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转贴】Lua常用资源连接(来自lua-users) </title><link>http://www.cppblog.com/mybios/archive/2006/11/18/15334.html</link><dc:creator>李锦俊(mybios)</dc:creator><author>李锦俊(mybios)</author><pubDate>Sat, 18 Nov 2006 01:35:00 GMT</pubDate><guid>http://www.cppblog.com/mybios/archive/2006/11/18/15334.html</guid><wfw:comment>http://www.cppblog.com/mybios/comments/15334.html</wfw:comment><comments>http://www.cppblog.com/mybios/archive/2006/11/18/15334.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/mybios/comments/commentRss/15334.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/mybios/services/trackbacks/15334.html</trackback:ping><description><![CDATA[
		<ul>
				<li>官方资源  
<ul><li><a href="http://www.lua.org/"><u><font color="#800080">[Lua 官方主页]</font></u></a></li></ul></li>
				<li>Lua社区  
<ul><li><a href="http://lua-users.org/lists/lua-l/"><u><font color="#0000ff">[Lua 邮件列表]</font></u></a></li><li><a href="irc://irc.freenode.net/lua"><u><font color="#800080">[Lua IRC 聊天频道]</font></u></a> (#来自irc.freenode.net) 
</li><li><a href="http://mini.net/cgi-bin/lua/"><u><font color="#0000ff">[Jean-Claude Wippler的wiki]</font></u></a>. <em>(不再维护)</em></li></ul></li>
				<li>Lua 文档 
<ul><li><em><a href="http://www.tecgraf.org/~mark/luaarchitecture.doc"><u><font color="#0000ff">[Lua架构]</font></u></a></em> - 描述了Lua的业务驱动方式，目的以及架构解决方案。</li></ul></li>
				<li>带有例证的Lua文档 
<ul><li><em><a href="http://www.acmqueue.org/modules.php?name=Content&amp;pa=showpage&amp;pid=112"><u><font color="#0000ff">[与Will Harvey的谈话记录]</font></u></a></em></li></ul></li>
				<li>Lua 教程 
<ul><li><a href="http://www.gamedev.net/reference/articles/article1932.asp"><u><font color="#0000ff">[来自GameDev.net的：An Introduction to Lua]</font></u></a></li><li><a href="http://davespalace.co.uk/tutorials/lua_extend.html"><u><font color="#0000ff">[扩展性的Lua]</font></u></a></li><li><a href="http://davespalace.co.uk/tutorials/lua_embed.html"><u><font color="#0000ff">[嵌入式的 Lua]</font></u></a></li><li><a href="http://smorgasbordet.com/phpBB2/viewtopic.php?p=778#778"><u><font color="#0000ff">[Win32平台下使用Pelles C编译Lua]</font></u></a></li><li><a href="http://www.blitzwiki.org/index.php/Introduction_to_Lua"><u><font color="#0000ff">[在BlitzMax中使用 Lua]</font></u></a></li></ul></li>
				<li>认证考试  
<ul><li><a href="http://www.high-levelcert.com/"><u><font color="#0000ff">[Lua高级认证]</font></u></a> 提供Lua认证考试和相关练习. </li></ul></li>
				<li>Benchmarks 
<ul><li><a href="http://cm.bell-labs.com/cm/cs/who/bwk/interps/pap.html"><u><font color="#0000ff">[Experiments with Scripting and User-Interface Language]</font></u></a> is a paper by Kernighan and Van Wyk that benchmarks several scripting languages. An <a href="http://www.inf.puc-rio.br/~roberto/bwk-lua.tar.gz"><u><font color="#0000ff">[implementation]</font></u></a> of these benchmarks in Lua is available. 
</li><li>Doug Bagley's的书： <a href="http://shootout.alioth.debian.org/"><u><font color="#0000ff">[Great Computer Language Shootout]</font></u></a> 的更新版本.还有一个不太新的<a href="http://dada.perl.it/shootout/"><u><font color="#0000ff">[Windows版本]</font></u></a> . </li></ul></li>
				<li>语言比较  
<ul><li><a href="http://www.latech.edu/~acm/HelloWorld.shtml"><u><font color="#0000ff">[Hello World!]</font></u></a></li><li><a href="http://kevin.alteu.com/code/helloyou/index.html"><u><font color="#0000ff">[Hello You]</font></u></a>: <a href="http://kevin.alteu.com/code/helloyou/lua.html"><u><font color="#0000ff">[Lua entry]</font></u></a>. 
</li><li><a href="http://www.99-bottles-of-beer.net/"><u><font color="#0000ff">[99 Bottles of Beer]</font></u></a>: <a href="http://www.99-bottles-of-beer.net/language-lua-365.html"><u><font color="#0000ff">[Lua entry]</font></u></a>. 
</li><li><a href="http://www.miranda.org/~jkominek/rot13/"><u><font color="#0000ff">[ROT13]</font></u></a>: <a href="http://www.miranda.org/~jkominek/rot13/lua/"><u><font color="#0000ff">[Lua entry]</font></u></a></li><li><a href="http://www.nyx.net/~gthompso/quine.htm"><u><font color="#0000ff">[The Quine Page]</font></u></a></li><li><a href="http://www.angelfire.com/tx4/cus/shapes/index.html"><u><font color="#0000ff">[OO 例子]</font></u></a></li><li><a href="http://www.kochandreas.com/home/language/lang.htm"><u><font color="#0000ff">[APLC: Andreas' 实践语言对比]</font></u></a>. 
</li><li><a href="http://***.sourceforge.net/pixel/language-study/scripting-language/"><u><font color="#0000ff">[Scriptometer]</font></u></a></li><li><a href="http://***.sourceforge.net/pixel/language-study/syntax-across-languages.html"><u><font color="#0000ff">[Syntax accross languages]</font></u></a> (Big page!) 
</li><li><a href="http://www.ntecs.de/old-hp/uu9r/lang/html/lang.en.html"><u><font color="#0000ff">[Michael Neumann's关于语言的比较]</font></u></a></li><li><a href="http://csl.sublevel3.org/lua/"><u><font color="#0000ff">[与C++一起使用Lua:简短的教程]</font></u></a></li><li><a href="http://pleac.sourceforge.net/"><u><font color="#0000ff">[PLEAC - 类似食谱一样的编程语言例子]</font></u></a></li></ul></li>
				<li>Lua 其他相关站点 
<ul><li><a href="http://groups.google.com/groups?as_q=Lua&amp;num=20&amp;as_scoring=date&amp;btnG=Google+Search&amp;as_ugroup=comp.*+*game*&amp;as_drrb=quick"><u><font color="#0000ff">[Lua使用指南]</font></u></a>, 来自 <a href="http://groups.google.com/"><u><font color="#0000ff">[Google Groups]</font></u></a>. 
</li><li><a href="http://www.ddj.com/topics/altlang/sites.htm?topic=altlang"><u><font color="#0000ff">[Dr. Dobb's 的脚本语言列表]</font></u></a>. 
</li><li><a href="http://www.idiom.com/free-compilers/"><u><font color="#0000ff">[免费的编译器和解释器分类]</font></u></a>: <a href="http://www.idiom.com/free-compilers/TOOL/lua-1.html"><u><font color="#0000ff">[Lua entry]</font></u></a>. 
</li><li><a href="http://www.erols.com/ziring/dopl.html"><u><font color="#0000ff">[编程语言字典]</font></u></a>: <a href="http://cgibin.erols.com/ziring/cgi-bin/cep/cep.pl?_key=Lua"><u><font color="#0000ff">[Lua entry]</font></u></a>. 
</li><li><a href="http://sal.kachinatech.com/"><u><font color="#0000ff">[SAL, Linux上的科学上的应用]</font></u></a>: <a href="http://sal.kachinatech.com/F/1/LUA.html"><u><font color="#0000ff">[Lua entry]</font></u></a> (site no longer exists?). 
</li><li><a href="http://freshmeat.net/"><u><font color="#0000ff">[Freshmeat]</font></u></a>: <a href="http://freshmeat.net/projects/lua/"><u><font color="#0000ff">[Lua entry]</font></u></a>. 
</li><li><a href="http://www.freebsd.org/"><u><font color="#0000ff">[FreeBSD]</font></u></a>: <a href="http://www.freebsd.org/ports/lang.html"><u><font color="#0000ff">[Lua entry]</font></u></a>. 
</li><li><a href="http://www.netbsd.org/"><u><font color="#0000ff">[NetBSD]</font></u></a>: <a href="ftp://ftp.netbsd.org/pub/NetBSD/packages/pkgsrc/lang/lua/README.html"><u><font color="#0000ff">[Lua entry]</font></u></a>. 
</li><li><a href="http://www.mathtools.net/"><u><font color="#0000ff">[Mathtools.net]</font></u></a>: <a href="http://www.mathtools.net/C++/Interpreters/Other/"><u><font color="#0000ff">[Lua entry]</font></u></a> (404 error). 
</li><li><a href="http://www.wikipedia.com/"><u><font color="#0000ff">[Wikipedia]</font></u></a>: <a href="http://wikipedia.org/wiki/Lua_programming_language"><u><font color="#0000ff">[Lua entry]</font></u></a>. 
</li><li><a href="http://www.conectiva.com/"><u><font color="#0000ff">[Conectiva]</font></u></a>: <a href="http://snapshot.conectiva.com/SRPMS/Interpreters/lua.html"><u><font color="#0000ff">[Lua entry]</font></u></a> (404 error). 
</li><li><a href="http://www.hypernews.org/HyperNews/get/computing/lang-list.html"><u><font color="#0000ff">[Hypernews Computer Language List]</font></u></a>. 
</li><li><a href="http://wuarchive.wustl.edu/doc/misc/lang-list.txt"><u><font color="#0000ff">[语言列表- Version 2.4]</font></u></a> (开始于1995年! 现在404错误, 到 <a href="http://wuarchive.wustl.edu/"><u><font color="#0000ff">[主页]</font></u></a> 察看原因). 
</li><li><a href="http://cliki.tunes.org/Programming%20Languages"><u><font color="#0000ff">[现存语言的评论]</font></u></a>: <a href="http://cliki.tunes.org/LUA"><u><font color="#0000ff">[Lua entry]</font></u></a>. 
</li><li><a href="http://dmoz.org/"><u><font color="#0000ff">[开源的工程目录]</font></u></a>: <a href="http://dmoz.org/Computers/Programming/Languages/Lua/"><u><font color="#0000ff">[Lua entry]</font></u></a>. 
</li><li><a href="http://www.gnu.org/directory/"><u><font color="#0000ff">[GNU 自由软件目录]</font></u></a>: <a href="http://www.gnu.org/directory/lua.html"><u><font color="#0000ff">[Lua entry]</font></u></a>. 
</li><li><a href="http://www.scriptol.org/choose.php"><u><font color="#0000ff">[流行的脚本语言]</font></u></a></li></ul></li>
		</ul>
<img src ="http://www.cppblog.com/mybios/aggbug/15334.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/mybios/" target="_blank">李锦俊(mybios)</a> 2006-11-18 09:35 <a href="http://www.cppblog.com/mybios/archive/2006/11/18/15334.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>