`
webcenterol
  • 浏览: 943712 次
文章分类
社区版块
存档分类
最新评论

数据/配置 的存储方式 Lua篇

 
阅读更多

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

讨论新闻组及文件

前言

在《数据/配置 的存储方式 Json篇 以JsonCpp库使用为例 》《数据/配置 的存储方式 Json篇 以Cocos2D For Iphone+TouchJson为例 》中我总结了一下怎么使用Json作为配置,但是,其实Json虽然语法格式简单,同时解析库的使用也非常简单,但是,因为这种简单性,缺少有的时候的确非常需要的功能。比如配置文件中对另一行配置的引用,比如配置段的继承等,这些可以使用XML来解决,另外,有的时候还会需要在配置文件中进行简单的运算,比如我就常常会有想将某个图片缩放到目前分辨率的几分之几这样的需求,此时,用一个完整的可以进行运算的语言来做配置的诱惑实在太大了。。。。。。
Lua就是为此而生的。。。。。。虽然现在Lua的功能已经远远不止这样了,但是最初设计Lua的目的就是一个简单的配置语言。见Lua的历史 。虽然其实用Python作为配置也完全可行,但是Lua有着速度快的优点,而且,Lua实在比Python小太多了,很适合嵌入到程序中去。

对于使用Lua作为配置,事实上就相当于在C++中嵌入Lua,只不过不用其脚本语言的一些复杂特性,仅仅将其作为一个配置文件来看。

这里还是以原来《数据/配置 的存储方式 Json篇 以JsonCpp库使用为例 》文中开始的SDL工程作为例子。

首先搭建可以内嵌使用Lua的C++编译环境,下载一个luabinaries 是简单的办法,现在我使用的是lua5_1_4_Win32_dll8_lib.zip 。这里我甚至不需要一个可以运行的Lua交互环境。。。。。

简单示例

首先建立一个简单的Lua文件,命名为picture.lua
name="dragon.png"
rotation=180

虽然只有简单的两行,也是个合法的Lua程序。

然后在C++程序中读取出来,这个过程实际上是使用了Lua的C API,具体的Lua的C API这里就不详细讲解了,那比较复杂,可以参考《Programming in Lua》,中文版也已经有了。这里仅仅作为一个例子提供参考吧。
现在可以开始完成C++的程序了:
首先,包含必要的头文件:
extern "C" {
#include "lua/lua.h"
#include "lua/lauxlib.h"
#include "lua/lualib.h"
}
因为lua的头文件完全是只考虑C语言的情况,所以在C++中使用的时候需要自己添加extern "C"。这是典型的对C++不屑的态度,因为现在大部分的纯C语言写的库,都会很自然的通过宏判断来自动使用extern "C"语句。

然后:
using namespace std;
struct PictureInfo {
string name;
float rotation;
}gPictureInfo;

void PictureInit() {
lua_State *L = luaL_newstate();
if ( luaL_dofile(L, "picture.lua" ) != 0 ) {
printf("Error happen." );
// handle the error.
exit(1 );
}

lua_getglobal(L, "name" );
assert(lua_isstring(L, -1 ) == 1 );

gPictureInfo.name = lua_tostring(L, -1 );

lua_getglobal(L, "rotation" );
gPictureInfo.rotation = (float )lua_tonumber(L, -1 );

lua_close(L);
}
这里我们使用的所有变量全部都是global的变量,所以调用起来非常方便。上面的主要内容就是对Lua C API的使用,由于其本身较为复杂,这里一下也讲不清楚。
基本流程是创建新的Lua state,然后用luaL_dofile 执行我们需要的配置文件,然后调用lua_getglobal 加适当的转换来获取我们需要的配置值。这里的例子是一个字符串和一个浮点数。
具体显示的效果和其他代码参考《数据/配置 的存储方式 Json篇 以JsonCpp库使用为例 》就好了,这里不重复描述了。

数组

在Lua中数组也通过table的形式来表示,这里我仅仅介绍怎么从lua文件中获取配置,具体的显示等东西也不再累述了。
这里,我们建立一个包含数组的lua文件作为配置:

data = {
{ name="dragon.png" , rotation=180 } ,
{ name="dragon.png" , rotation=0 }
}

下面看怎么将配置读取出来:

using namespace std;
struct PictureInfo {
string name;
float rotation;
};

vector gPictureInfoVec;

void PictureInit() {
lua_State *L = luaL_newstate();
if ( luaL_dofile(L, "picture.lua" ) != 0 ) {
printf("Error happen." );
// handle the error.
exit(1 );
}

// get the table
lua_getglobal(L, "data" );
assert(lua_istable(L, -1 ) == 1 );

/* table is in the stack at index 't' */
lua_pushnil(L);/* first key */
while (lua_next(L, -2 ) != 0 ) {
PictureInfo info;
/* 'key' (at index -2) and 'value' (at index -1) */

// push the key to stack for getting the value
lua_pushstring(L, "name" );

// now the table is in the -2 and key in the top(-1)
lua_gettable(L, -2 );
assert(lua_isstring(L, -1 ));

info.name = lua_tostring(L, -1 );

lua_pop(L, 1 );

// push the key to stack for getting the value
lua_pushstring(L, "rotation" );

// now the table is in the -2 and key in the top(-1)
lua_gettable(L, -2 );
assert(lua_isnumber(L, -1 ));

info.rotation = lua_tonumber(L, -1 );

gPictureInfoVec.push_back(info);
/* removes the key we pushed and the 'value' of the global table ; keeps 'key' for next iteration */
lua_pop(L, 2 );
}

lua_close(L);
}

代码中的注释解释的已经够详细了,但是因为Lua 的API的确不是太容易理解,这里也无法一下讲清楚,所以还是先了解Lua 的 API为好,具体的API的意义可以参考参考手册
上面仅仅使用了Lua API遍历数组以及从table中获取元素的方法。
假如仅仅只有上面这些,是看不出用lua作为配置的好处的,用lua做配置的好处在于可以利用lua的特性实现配置段之间的继承以及完整的运算功能。
比如说,完全不用修改上面的读取配置的代码,我们仅仅修改配置,看看在Lua中使用上述功能:

data1 = { name="dragon.png" , rotation=180 }
data2 = { name = data1.name, rotation = data1.rotation / 2 }
data = {
data1, data2
}

此时,data2的数据完全依赖于data1的数据,当有任何东西需要修改的时候,你只需要修改一个地方,对于配置来说,don't repeat yourself也是很有意义的。最最重要的的是,在配置中能够进行计算那是非常强大,即使完全不用lua的函数功能与代码的交互,仅仅通过lua的计算,也可以完成游戏中所有sprite的布局。。。。。。

小结

相对于使用XML,Json,使用Lua作为配置绝对是最最强大的。。。。。。作为一个完整的语言,它拥有你想在配置中实现的一切功能。但是缺点也是很明显的:
首先,速度上,Lua需要解释运行,可能明显跟不上XML或者Json的解析速度。但是,配置的解析读取可以都放在初始化阶段,所以配置不是太多的时候,也不算太过难以接受,另外,还可以将lua的配置完全作为开发期的一种机制使用,在发布后完全转化为2进制数据。
其次,Lua的配置读取需要手动调用Lua的API来完成,相对于XML,Json那种有很方便的库的情况,使用上还是麻烦一些,特别是Lua的API的使用并不是那么简单易懂,不算太直观。但是,这也不是不可以克服的,完全可以自己写个小型的库将Lua的API封装起来,形成一个类似JsonCpp那样的库,用Map来表示一切。这个可能需要限制一些Lua语法的时候,或者在解析的时候进行取舍,比如函数啥的可能需要过滤掉,不然那就不太像将Lua作为配置使用了。
还有,Lua的配置的生成更加是没有XML,Json那样有完善库支持来的方便,这点暂时没有办法克服,写一个自动生成Lua配置文件的库感觉并不是太过容易的事情。而且,自动生成时,lua的优势其实并没有余地发挥出来,那样的话,还不如使用Json。
总的来说,假如是没有工具,需要大量手写配置的话,对Lua的API进行一层简单的封装,然后使用Lua来做配置,那还是件很爽的事情,需要手写的时候,你才会感觉到一个完整语言作为配置给你带来的好处。

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie






分享到:
评论

相关推荐

    lua的lpack工具库

    在Lua环境中,lpack库提供了一种高效的方式将 Lua 表转换为二进制格式,便于在网络传输中节省带宽,并且能够在接收端通过解包还原为原来的表结构。这个库是针对 Lua 5.1.5 版本设计的,并且与 VC2015 集成,使得...

    json转lua-table工具

    JSON因其简洁明了的结构而被广泛用于数据交换,而Lua Table则是Lua编程语言中的核心数据结构,用于存储各种类型的数据。本文将详细介绍如何使用Python脚本`jsonToLua.py`将JSON数据转换为Lua Table格式,并探讨相关...

    Excel配置转Lua文件

    通过将这些数据配置在Excel中,非程序员的设计师也能方便地修改和调整。而转换成Lua后,这些数据可以直接在游戏运行时被读取和使用,降低了数据维护的门槛,同时也使得数据与代码分离,符合良好的软件工程实践。 在...

    lua+nginx动态更新配置.zip

    更新频率比较慢,使用lua_shared_dict进行存储。如下定义: lua_shared_dict sysconfig 10k; 成员包括: "time":配置文件的生成的时间戳(用来判断文件是否有更新)eg:1585209315 "kxsip":与可信控制服务数据交互...

    lua_cjson_2.1.0

    Lua_cjson是一个为Lua语言设计的JSON编码和解码库,它提供了高效的转换机制,将JSON数据格式与Lua数据类型之间进行互转。在本文中,我们将深入探讨lua_cjson 2.1.0版本,它是这个库的一个关键里程碑,支持在Visual ...

    Lua的最基本使用 C++与lua的互相调用

    使用`lua_pushnumber`、`lua_pushstring`等函数将C++数据推送到Lua栈,使用`lua_tonumber`、`lua_tostring`等函数从Lua栈获取数据。 6. 清理:调用`lua_settop(L, 0)`清空栈,防止内存泄漏。 二、Lua调用C++函数 ...

    protobuf转为lua代码

    这种方式可以方便地进行数据交换和存储。 描述中提到“protobuf配置文件转化为lua脚本”,这通常用于游戏开发。在游戏开发中,由于Lua语言的轻量级和易嵌入性,经常被用来作为游戏逻辑或配置的脚本语言。protobuf则...

    lua脚本快速入门手册

    - 配置文件:游戏的配置信息常以LUA脚本形式存储,方便修改和调试。 - 热更新:LUA脚本可动态加载,实现游戏热更新,减少用户下载量。 5. **LUA性能优化** - 代码效率:LUA的解释器执行速度快,但合理优化代码...

    Lua中文教程,高清PDF文档

    Lua中的数据类型包括:数值(包括整型和浮点型)、字符串、布尔型、表(相当于数组或关联数组)、函数、nil和用户数据。 **表和元表** 表是Lua的核心数据结构,可以用来表示数组、集合、记录、对象等。表是动态...

    对lua栈的简单操作

    Lua的运行机制中,所有数据都在一个称为“虚拟机栈”的地方存储和操作。这个栈按照后进先出(LIFO)的原则工作,就像一个堆栈一样。当你在Lua中调用函数或创建变量时,这些操作都会涉及到栈的操作。 在C/C++中,...

    Lua 5.2 Reference Manual(Lua 5.2引用指南)

    ### Lua 5.2 参考手册核心知识点详解 #### 一、引言与概述 **Lua** 是一种扩展编程语言,旨在支持通用的...无论是作为游戏开发中的脚本语言还是作为 Web 开发中的配置语言,Lua 都展现出了其独特的优势和强大的功能。

    LuaXml工具

    XML(eXtensible Markup Language)是一种广泛用于存储和传输结构化数据的标记语言,而Lua则是一种轻量级、灵活且高效的脚本语言,常用于游戏开发、嵌入式系统以及各种配置文件的编写。 LuaXML库主要包含以下几个...

    excel转lua工具

    在游戏开发、数据配置或者需要处理大量结构化数据的项目中,这种工具尤其常见。Lua因其轻量级、易读易写和高性能的特点,常被用作游戏中的脚本语言,而Excel则是广泛使用的数据管理和分析工具。通过将Excel数据转换...

    lua-cjson-2.1.0

    2. **序列化Lua数据**:相反,`encode`函数可以将Lua的数据结构转化为JSON字符串,方便数据传输或存储。 3. **速度与效率**:`lua-cjson`使用C语言编写,因此比纯Lua实现的JSON库在性能上有显著优势,特别是在处理...

    Lua与C交互示例

    3. **light userdata**:轻用户数据(light userdata)是C指针在Lua中的表示,它只是简单地存储一个指针,没有关联的元表。 4. **full userdata**:全用户数据(full userdata)允许C在Lua中创建自定义类型,并可以...

    Lua程序设计.pdf_lua_nginx_

    变量在Lua中是动态类型的,可以存储任何类型的数据,包括整数、浮点数、字符串、布尔值以及nil。数据类型的多样性使Lua具有极高的灵活性。控制结构如if语句、while和for循环用于逻辑流程控制。函数是第一类公民,...

    lua文件暂存

    2. Lua序列化与反序列化:探讨如何将数据结构转换为字符串以便存储或传输,以及如何恢复这些数据,可能提到了`serpent`或`moonscript`等库。 3. 错误处理:讲解了如何在 Lua 中使用`pcall`和`xpcall`来捕获和处理...

    excel表转Lua脚本工具

    而Lua脚本则常用于存储配置信息,因为它具有清晰的语法结构和良好的可读性。通过"Excel表转Lua脚本工具",我们可以利用Excel的易用性编辑数据,然后利用工具将其转换为Lua代码,使这些数据可以直接在项目中使用。 ...

    LUA编程(programming in lua).pdf

    LUA以其简洁的语法、高效性能和灵活性在游戏开发、系统配置、嵌入式系统等多个领域得到广泛应用。以下是基于书中的内容,对LUA编程的一些关键知识点的详细阐述: 1. **LUA语法基础**:LUA语法简洁明了,易于学习。...

    lua-5.4.1.tar.gz

    同时,`lua/`和`luac/`提供了一个简单的交互环境来实践和理解语言特性。对于开发者来说,`src/lua.c`和`src/luai_*.h`文件是理解Lua核心机制的关键。 总的来说,`lua-5.4.1.tar.gz`提供的源码不仅是一个可学习和...

Global site tag (gtag.js) - Google Analytics