第25章 扩展你的程序

作为配置语言是LUA的一个重要应用。在这个章节里,我们举例说明如何用LUA设置一个程序。让我们用一个简单的例子开始然后展开到更复杂的应用中。

首先,让我们想象一下一个简单的配置情节:你的C程序(程序名为PP)有一个窗口界面并且可以让用户指定窗口的初始大小。显然,类似这样简单的应用,有多种解决方法比使用LUA更简单,比如环境变量或者存有变量值的文件。但,即使是用一个简单的文本文件,你也不知道如何去解析。所以,最后决定采用一个LUA配置文件(这就是LUA程序中的纯文本文件)。在这种简单的文本形式中通常包含类似如下的信息行:

-- configuration file for program `pp'

-- define window size

width = 200

height = 300

现在,你得调用LUA API函数去解析这个文件,取得widthheight这两个全局变量的值。下面这个取值函数就起这样的作用:

#include <lua.h>

#include <lauxlib.h>

#include <lualib.h>

 

void load (char *filename, int *width, int *height) {

    lua_State *L = lua_open();

    luaopen_base(L);

    luaopen_io(L);

    luaopen_string(L);

    luaopen_math(L);

 

    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");

    if (!lua_isnumber(L, -2))

       error(L, "`width' should be a number\n");

    if (!lua_isnumber(L, -1))

       error(L, "`height' should be a number\n");

    *width = (int)lua_tonumber(L, -2);

    *height = (int)lua_tonumber(L, -1);

 

    lua_close(L);

}

首先,程序打开LUA包并加载了标准函数库(虽然这是可选的,但通常包含这些库是比较好的编程思想)。然后程序使用luaL_loadfile方法根据参数filename加载此文件中的信息块并调用lua_pcall函数运行,这些函数运行时若发生错误(例如配置文件中有语法错误),将返回非零的错误代码并将此错误信息压入栈中。通常,我们用带参数index值为-1lua_tostring函数取得栈顶元素(error函数我们已经在24.1章节中定义)。

解析完取得的信息块后,程序会取得全局变量值。为此,程序调用了两次lua_getglobal函数,其中一参数为变量名称。每调用一次就把相应的变量值压入栈顶,所以变量widthindex值是-2而变量heightindex值是-1(在栈顶)。(因为先前的栈是空的,需要从栈底重新索引,1表示第一个元素2表示第二个元素。由于从栈顶索引,不管栈是否为空,你的代码也能运行)。接着,程序用lua_isnumber函数判断每个值是否为数字。lua_tonumber函数将得到的数值转换成double类型并用(int)强制转换成整型。最后,关闭数据流并返回值。

Lua是否值得一用?正如我前面提到的,在这个简单的例子中,相比较于lua用一个只包含有两个数字的文件会更简单。即使如此,使用lua也带来了一些优势。首先,它为你处理所有的语法细节(包括错误);你的配置文件甚至可以包含注释!其次,用可以用lua做更多复杂的配置。例如,脚本可以向用户提示相关信息,或者也可以查询环境变量以选择合适的大小:

-- configuration file for program 'pp'

if getenv("DISPLAY") == ":0.0" then

    width = 300; height = 300

else

    width = 200; height = 200

end

在这样简单的配置情节中,很难预料用户想要什么;不过只要脚本定义了这两个变量,你的C程序无需改变就可运行。

最后一个使用lua的理由:在你的程序中很容易的加入新的配置单元。方便的属性添加使程序更具有扩展性。


相关链接:
lua程序设计目录 - 中国lua开发者 - lua论坛