TimothyQiu's Blog

keep it simple stupid

Lua 学习笔记:零

分类:技术

其实本来用过一点点 Lua,不过都是需要什么功能就慢慢找 Reference Manual,这回毕业设计终于要用 Lua 写完整的东西了,于是准备把 PIL 慢慢看一遍。

首先是最简单的 Lua 为 C/C++ 程序变量赋值,类似史前的 INI 配置文件。

width = 640
height = 480

这样的赋值即设置全局变量,本质上就是在全局表中添加字段。

在 C/C++ 中,Lua 其实并不是直接去改变变量的值,而是宿主程序通过「读取脚本中设置的全局变量到栈、类型检查、从栈上取值」几步去主动查询。

int w, h;
if (luaL_loadfile(L, fname) || // 读取文件,将内容作为一个函数压栈
    lua_pcall(L, 0, 0, 0))     // 执行栈顶函数,0个参数、0个返回值、无出错处理函数(出错时直接把错误信息压栈)
    error();

lua_getglobal(L, "width");     // 将全局变量 width 压栈
lua_getglobal(L, "height");    // 将全局变量 height 压栈
if (!lua_isnumber(L, -2))      // 自顶向下第二个元素是否为数字
    error();
if (!lua_isnumber(L, -1))      // 自顶向下第一个元素是否为数字
    error();
w = lua_tointeger(L, -2);      // 自顶向下第二个元素转为整型返回
h = lua_tointeger(L, -1);      // 自顶向下第一个元素转为整型返回

读取表的字段的操作也是类似,只不过细节上比较麻烦,有点让我想起在汇编里调戏各种寄存器:

score = { chinese=80, english=85 }

int chinese, english;
if (luaL_loadfile(L, fname) || lua_pcall(L, 0, 0, 0))
    error();

lua_getglobal(L, "score");       // 全局变量 score 压栈

lua_pushstring(L, "chinese");    // 字符串 math 压栈
lua_gettable(L, -2);             // 以自顶向下第二个元素为表、第一个元素为索引取值,弹栈,将该值压栈
if (!lua_isnumber(L, -1))        // 栈顶元素是否为数字
    error();
chinese = lua_tointeger(L, -2);
lua_pop(L, 1);                   // 弹出一个元素 (此时栈顶为 score 变量)

lua_getfield(L, -1, "english");  // Lua5.1开始提供该函数简化七八两行
if (!lua_isnumber(L, -1))
    error();
english = lua_tointeger(L, -2);
lua_pop(L, 1);                   // 如果就此结束,这一行弹不弹都无所谓了

前面说过,设置全局变量本质就是在全局表中添加字段,所以 lua_getglobal 函数本质是从全局表中读取字段。没错,lua_getglobal 本身就是一个宏:

#define lua_getglobal(L,s)  lua_getfield(L, LUA_GLOBALSINDEX, s)

LUA_GLOBALSINDEX 指明的就是全局表的索引。

于是基本上今天就看了这么多……

TO BE CONTINUED...

Lua

添加新评论 »