介绍

Lua的设计和实现目标:提供一种嵌入式的脚本编程语言,简洁、高效、可移植并且是轻量级的。

传统上大部分虚拟机都是基于堆栈的,自Pascal的P-虚拟机开始一直到今天的Java虚拟机以及Microsoft.Net。Lua5.0的虚拟机是基于寄存器的虚拟机,Perl6(Parrot)也是。

简洁:寻求最简化的语言和最小化的源码(以C语言实现)。这也意味着Lua只有一些类似传统编程语言的简单的语法和少量的语言结构。

可移植:我们希望Lua能够在尽可能多的平台上运行。希望Lua内核能够在不做任何修改的情况下,在任何平台下都能顺利通过编译。并且希望Lua程序在任何平台下都不需要修改就能顺利执行,只要该平台上又一个Lua解释器。这也意味着需要用纯ANSI C实现Lua并注意移植问题,避开C语言及其库的阴暗面,并保证在C++编译器上也能顺利通过编译,而不希望看到警告信息。

可嵌入:Lua是一种可扩展的语言,我们希望能够容易地将Lua嵌入到应用程序中。

值的内部表示

Lua是动态类型的语言:类型是与值相关而不是与变量相关。Lua有8种基本的值类型:nil,boolean,number,string,table,function,userdate和thread。

nil:是标记类型,只有一种值,就是nil。

boolean:有true和false两种值。

number:双精度浮点数,对应C语言的double,不过可以在编译Lua的时候将其设置为float或long型。(一些小型机缺乏支持double数据类型的硬件)

string:字节数组,有一个显示的长度,因此可以容纳任何二进制数,包括0。

table:关联数组,可以通过任何值(除nil)来索引,也能容纳任意值。

function:可以是Lua函数或根据Lua虚拟机接口函数的原型编写的C函数。

userdata:一个指向用户内存块的指针,分两种情况:

heavy,内存由Lua分配,并由垃圾回收机制负责处理;

light,内存由用户分配并释放。

thread:代表协程。

任何类型都是first-class的:可以被存入全局变量、局部变量或table域中,或作为实际参数传递给参数,或从函数中返回。

Lua将值表示成带标志的联合结构,即(t,v)对,其中t是个整数,代表值v的类型,v是一个C语言union类型数据结构,存储实际的值。

typedef struct {int t;Value v;
} TObject;typedef union {GCObject *gc;void *p;lua_Number n;int b;
} Value;

Value的n域用于表示number;b域用于表示boolean;p域用于表示light userdata;gc域用于需要垃圾回收机制处理的其他值(如 string, table,function,heavy userdata,thread等)

Lua用一个散列表将string内部化:Lua为每个字符串只保留一份拷贝,而且字符串是不变的:一旦内部化,字符串将不可更改。

表是Lua中唯一的表示数据结构的工具。Lua中没有内置对数组类型的支持,数组使用表和整数索引来模拟的。例如,在Perl中,如果你试图执行程序:$a[10000000000]=1;可能导致内存不足,因为这会导致Perl创建一个用用10亿个元素的数组,而等价的Lua程序:a={[10000000000]=1};创建的表只有一个表项。

截至Lua4.0版,表都是严格的以散列表(哈希表)实现的:所有的键、值都明确的存在于表中。在Lua5.0,表以一种混合型数据结构来实现,它包含一个散列表部分和一个数组部分。对于键、值对"x"->9.3,1->100,2->200,3->300,存储方式如下图

当表需要增长时,最初表的两个部分有可能都是空的。新的数组部分的大小是满足以下条件的最大的 n 值:1到 n 之间至少一半的空间会被利用(避免像稀疏数组一样浪费空间);并且 n/2+1到 n 之间的空间至少有一个空间被利用(避免 n/2 个空间就能容纳所有数据时申请 n 个空间而造成浪费)。当新的大小计算出来后,Lua 为数组部分重新申请空间,并将原来的数据存入新的空间。举例来说,假设 a 是一个空表,散列表部分和数组部分都是 0 大小。如果执行 a[1]=v,那么表就需要增长以容纳新键。Lua 会选择 n=1 作为新数组的大小(存储一个数据 1→v)。散列表部分仍保持为空。

这种混合型结构有两个优点。第一,存取整数键的值很快,因为无需计算散列值。第二,也是更重要的,相比于将其数据存入散列表部分,数组部分大概只占用一半的空间。

函数和闭包

线程和协同程序(协程)

虚拟机

Lua解释器在执行Lua程序时,首先将源码编译成虚拟机指令(opcode,操作码),然后执行这些指令。对每一个被编译的函数,Lua 为其创建一个原型,原型中含有一个由该函数的虚拟机指令组成的数组、一个所有被该函数用到的常数值(TObjects,字符串或实数)的数组(译者注:这很重要,因为这避免了在指令码中直接包含常数值进而导致指令长度的膨胀。事实上,可以把这些常数看成具有只读属性的全局变量,对它们的处理和全局变量的处理是一致的)。

在十年的时间里(从 1993 年 Lua 发布开始),各种版本的 Lua 都使用基于堆栈的虚拟机。从 2003 年开始,随着 Lua5.0 的发布,Lua 改用个基于寄存器的虚拟机。新的虚拟机也用堆栈分配活动记录,寄存器就在该活动记录中。当进入Lua 程序的函数体时,函数从栈中预分配一个足以容纳该函数所有寄存器的活动记录。函数的所有局部变量都各占据一个寄存器。因此,存取局部变量是相当高效的。

使用寄存器式虚拟机消除了用堆栈式虚拟机时为了在栈中拷贝数据而必需要的大量出入栈(push/pop)指令。在 Lua 中,这些出入栈指令相当费时,因为它们需要拷贝带标志的值(tagged value, TObject)正如第三节讨论过的。因此寄存器结构既消除了昂贵的值拷贝操作,又减少了为每个函数生成的指令码数量。Davis al.[6]反对基于寄存器的虚拟机,并以了 Java 虚拟机的字节码作为反证。某些编译器作者也因为可以很容易在编译期间为堆栈式虚拟机生成代码而反对寄存器式虚拟机。

与寄存器式虚拟机相关的两个难题是:指令大小和译码速度。寄存器式虚拟机的指令需要指明操作数位置,因此通常要比堆栈式虚拟机的同类指令长。(例如,当前 Lua 虚拟机的指令长度是 4 字节,而其他许多典型的堆栈式虚拟机的指令长度只有 1-2 字节,包括前一版本的 Lua 也是。)另一方面,为基于寄存器的虚拟机生成的操作码要比堆栈式虚拟机少,因此指令总长度大不了多少。堆栈式虚拟机的许多指令都有隐含的操作数。而寄存器式虚拟机中对应的指令需要从其中解码出操作数。解码过程增加了解释器的负担。有几个因素会淡化这种负面影响,第一,堆栈式虚拟机也花费一些时间处理隐含的操作数(例如,增减栈指针)。第二,由于寄存器式虚拟机中所有操作数都在指令中,而指令是一个机器字,对操作数的解码过程只包含一些很廉价的操作,如逻辑运算。另外 ,堆栈式虚拟机的指令常常需要多字节操作数。如 Java 虚拟机 JVM 的跳转和分支指令用了两字节的偏移量。出于对齐的关系,解释器无法一次获取这样的操作数(至少对于可移植的代码来说是如此,因为它必须总是假定最坏对齐的限制条件)。在寄存器式虚拟机上,由于操作数在指令里面,解释器无需单独获取它们。Lua 虚拟机有 35 条指令。大部分的指令直接对应着语言结构:数学运算、表的创建和索引、函数和方法调用、存取变量值等。也有一套用于实现控制结构的常规跳转指令。下图 列出了全部指令及其简短用法。一些符号的意义如下:R(X)是第 X 个寄存器;K(X)是第 X 个常数;RK(X)是 R(X)或 K(X-k),取决于 X 的值---当 X<k(一个内置参数,一般是 250)时,取 R(X)。 G[X]是全局变量表的 X 域。U[X]是第 X 个 upvalue。

寄存器保存在运行栈中,它们实质是一个数组。因此存取寄存器是很快的。常数和全局变量也存于不同数组中,因此存取它们也很快。全局变量表是一个普通的 Lua 表,虽然要通过散列法来存取其域,但其实是很高效的,因为它是由(对应于全局变量名的)字符串来索引的,而字符串散列值是已被预先计算出来了的。

Lua游戏开发(一)---Lua语言相关推荐

  1. 基于游戏开发的C语言大作业视频集锦

    基于游戏开发的C语言大作业视频集锦 从2014年至今,尝试了基于游戏开发的C语言程序设计教学,每次课程均会布置大作业,以下视频为一些学生做的大作业视频集锦. 基于游戏开发的C语言大作业视频集锦 后续, ...

  2. 游戏开发适合什么语言?

    游戏开发适合什么语言?哪种语言最好呢?今天就来跟大家分享下! 1.先说结论: 现代各种领域的开发技术已经成熟,不再能随意选择开发语言和技术栈,绝大多数情况下只能使用比较流行的方案.工具.和语言. 以上 ...

  3. 《Lua游戏开发实践指南》一3.2游戏项目中的Lua

    3.2游戏项目中的Lua 把脚本语言集成到游戏项目中可以提升团队的开发效率,并且可以很好地扩展原生编译语言的能力.Lua在游戏开发的许多基础领域中都表现得很出色. 在游戏开发团队中,可能有许多成员都使 ...

  4. 游戏开发入门——Lua(1)

    Lua(1)2018年7月6日 9:46 Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能. Lua 是巴 ...

  5. 【游戏开发】Lua Love2d | Love2d基础知识

    小提示: 此系列文章属于个人学习笔记,如果其中有误,希望大家指正. 也希望大家能够提出一些游戏开发学习上的建议等等的~ 谢谢大家!(๑•̀ㅂ•́)و✧ 教程简介: 了解如何使用 LOVE 2D 和 L ...

  6. 《LUA游戏开发实践指南》学习笔记1

    本文只做个人学习笔记! Lua脚本语言的优点:免费.小巧.快速和易移植. 游戏项目中的Lua,可以完成以下工作 编辑游戏用户界面(玩家和你的游戏进行交互的媒介) 定义.存储和管理游戏数据(Lua本人并 ...

  7. lua游戏开发实践指南光盘_Godot游戏开发实践之一:用High Level Multiplayer API制作多人游戏(上)

    一.前言 距离上一次发文已经稳稳超过一年了,去年一直在做 #¥@#*!%--%#&-%&^# 然后待在家里了!偶尔写写 BUG ,一直默默关注着 Godot ,这不已经 3.2.2 版 ...

  8. lua游戏开发实践指南光盘_Godot游戏开发实践之三:容易被忽视的Resource

    一.前言 首先,特大喜讯,奔走相告, Godot 爱好者们又有新的窝了--我们国人自建的 Godot 论坛:Godot中文社区已经正式开放,这里有一手的开发资源,最新的科技动向,开发上有啥问题可以随时 ...

  9. Lua游戏开发----模块

    1:游戏目录结构对模块的理解: Base,Common,Game这三个文件夹下都有自己的moduleConfig文件. base文件夹下的moduleConfig.lua文件是存放游戏基础的模块(例如 ...

最新文章

  1. 修改jenkins启动的默认用户
  2. maven打jar包,导入本地jar
  3. bboss hadoop hdfs大数据抽取工具
  4. Shell:传递命令行参数
  5. Effective java 系列之更优雅的关闭资源-try-with-resources
  6. 模型压缩高达75%,推理速度提升超20%,百度Paddle Lite v2.3正式发布
  7. Java日志性能那些事
  8. QQ空间说说的表情添加的代码
  9. java对接支付宝微信银联_JavaWEB后端支付银联,支付宝,微信对接
  10. OpenSSL 1.1.1 新特性: 全面支持国密SM2/SM3/SM4加密算法
  11. OpenCV学习笔记(一):读取、显示、保存图片
  12. 频谱分析仪二次开发|频谱分析仪程控软件NS-Analyzer
  13. Android: Android源码下载方法详解
  14. “绿坝-花季护航”软件
  15. 计算机毕业设计HTML+CSS+JavaScript仿大型购物商城(1页)
  16. 深度操作系统deepin下载与安装教程-系统安装
  17. Mycat的概述及部署安装
  18. 物联网蓝牙芯片的选型
  19. 浅析Android字体加载原理
  20. 如何关闭华为手机连接电脑自动弹出cd驱动器和类似文件管理文件夹

热门文章

  1. 【服务器数据恢复】硬盘坏道和不稳定扇区导致服务器崩溃的数据恢复案例
  2. 分享开源的GB/T-2260国家行政区划代码
  3. Error loading Python DLL python27.dll (error code 14001)
  4. java给图片添加水印工具类
  5. (C语言)冒泡排序法(含代码)
  6. CMDBuild2.5.1在wind10中使用
  7. ORA-01017(:用户名/口令无效; 登录被拒绝)Oracle新建用户并授权
  8. 电容器的电介质吸收(DA)现象
  9. DSOframer 的简单介绍和资源整理
  10. 2020大学计算机慕课答案,2020MOOC大学计算机最新查题答案