Lua1.1 Lua 的参考手册 (二)

转载出处:http://my.oschina.net/xhan/blog/310017

 

(接上篇)

 

--------------------------------------

5 API

--------------------------------------

这节主要描述 Lua 的 API, 也就是宿主程序和库交互的一组 C 函数。API 函数可以分为以下几类:

1. 执行 Lua 代码;

2. 在 Lua 和 C 之间进行值的转化;

3. 操作(读写)Lua 对象;

4. 调用 Lua 函数;

5. 由 Lua 调用的 C 函数;

6. 错误处理。

 

所有的 API 都在文件 lua.h 中声明。除非另有说明,API 函数返回一个错误码:0 为成功,非 0 为失败。

 

-------------------

5.1 执行 Lua 代码

-------------------

一个宿主程序可以执行写在文件中或在字符串中的 Lua 代码,使用下面的函数:

int lua_dofile (char *filename);

int lua_dostring (char *string);

 

-------------------

5.2 在 Lua 和 C 之间进行值的转化

-------------------

因为 Lua 没有静态的类型系统,所有的在 Lua 和 C 之间传递的值的类型为 lua_Object,它像是 C 中的可保存任何 Lua 值的一个抽象的类型。 lua_Object 声明如下:

typedef struct Object *lua_Object;

Object 没有在 lua.h 中声明。

 

Lua 有垃圾回收。所以,不保证在一个 lua_Object 是可用的在执行了其它的 Lua 代码之后。一个好的编程实践是在这些值可用的时候把它转化为 C 语言的值,并且永远不要把它们保存在全局变量中。

 

可以使用下面的函数来检查一个 lua_Obejct 的类型:

int lua_isnil (lua_Object object);

int lua_isnumber (lua_Object object);

int lua_isstring (lua_Object object);

int lua_istable (lua_Object object);

int lua_iscfunction (lua_Object object);

int lua_isuserdata (lua_Object object);

它们返回 1 如果类型是指定的类型的话, 否则返回 0。

 

可以使用下面的函数把一个 lua_Object 转化为 C 类型:

float lua_getnumber (lua_Object object);

char *lua_getstring (lua_Object object);

char *lua_copystring (lua_Object object);

lua_CFunction lua_getcfunction (lua_Object object);

void *lua_getuserdata (lua_Object object);

lua_getnumber 可以把一个 lua_Obejct 转化为一个浮点数。这个 lua_Object 必须是一个数字或者一个可以转化为数字的字符串(见 4.2 节);否则,该函数返回 0。

 

lua_getstring 把 lua_Object 转化为一个 string(char *)。这个 lua_Object 必须是一个字符串或者一个数字;否则,该函数返回 0 (空指针)。该函数不会创建一个新的字符串,它只是返回一个指向 Lua 环境中的字符串的指针。因为 Lua 有垃圾回收,没有什么保证这个指针在执行了另外的 Lua 代码之后依然有效。函数 lua_copystring 表现和 lua_getstring 完全一样,但是它返回那个字符串的一个全新拷贝。

 

lua_getfunction 把 lua_Object 转化为一个 C 函数。这个 lua_Obejct 类型必须为 Cfunction; 否则返回 0 (空指针)。类型 lua_CFunction 在 5.5 节中解释。

 

lua_getuserdata 把 lua_Object 转化为一个 void *。这个 lua_Obejct 类型必须为 userdata; 否则返回 0 (空指针)。

 

相反,把一个 C 类型转化为 lua_Obejct 类型用以下的函数:

int lua_pushnumber (float n);

int lua_pushstring (char *s);

int lua_pushcfunction (lua_CFunction f);

int lua_pushuserdata (void *u);

这些函数都接受一个 C 值,把它转化为 lua_Object,并把结果保存在 Lua 栈顶,在那里它可以被赋值给一个变量,做为参数传递给一个 Lua 函数,等(见下文)。为了完成设置,nil 或者 lua_Object 也可以压栈,用下面的函数:

int lua_pushnil (void);

int lua_pushobject (lua_Object object);

 

-------------------

5.3 操作Lua 对象

-------------------

可以使用以下的函数读取 Lua 全局变量的值:

lua_Object lua_getglobal (char *varname);

 

把前先压到栈顶的一个值保存到一个全局变量,用下面的函数:

int lua_storeglobal (char *varname);

 

表也可以通过 API 来操作,给定一个表,函数:

lua_Object lua_getindexed (lua_Object table, float index);

lua_Object lua_getfield (lua_Object table, char *field);

返回索引的内容。第一个用数字索引,第二个用任何的字符串索引。因为在 Lua 中,如果一个索引不在表中的话,返回的 Lua_Object 的值为 nil。

 

把前先压到栈顶的值保存到 Lua 表中的话,可以使用以下函数:

int lua_storeindexed (lua_Object object, float index);

int lua_storefield (lua_Object object, char *field);

同样,第一个用数字索引,第二个用字符串索引。

-------------------

5.4 调用 Lua 函数

-------------------

在宿主程序中可以调用由模块执行 dofile 或者 dostring 定义的函数。这采用如下的协议:前行,函数参数压到 Lua 栈上(详见 5.2 节),压栈的顺序和参数一致,也就是第一个参数首先压栈。然后,函数调用可以用:

int lua_call (char *functionname, int nparam);

第二个参数(nparam)是被压到栈上的值的个数。最后,返回的值(Lua 函数可以返回多个值)以逆序出栈,也就是最后一个返回值最先出栈。出栈用下面的函数:

lua_Object lua_pop (void);

当没有返回值可出栈时,函数返回 0。

7.5 节有一个 C 代码调用 Lua 函数的例子。

 

-------------------

5.5 C 函数

-------------------

注册 C 函数到 Lua ,用下面的宏:

#define lua_register(n,f) (lua_pushcfunction(f), lua_storeglobal(n))

/* char *n; */

/* lua_CFunction f; */

它接受函数在 Lua 中的名字,一个函数指针。这个指针的类型必须为 lua_CFunction,其定义为:

typedef void (*lua_CFunction) (void);

也就是一个无参无返回值的函数指针。

 

为了和 Lua 正确的交互,C 函数必须遵守一个协议,这个协议规定了参数和返回值传递的方法。

为了得到它的参数,C 函数调用 :

lua_Object lua_getparam (int number);

number 从 1 开始返回第一个参数。当用一个大于参数实际个数的值来调用时,该函数返回 0。用这种方法,写可变参数个数的函数就是可行的。

为了从 C 返回值到 Lua, C 函数可以把返回值顺序压栈;见 5.2 节。就像 Lua 函数一样,一个由 Lua 调用的 C 函数也可以返回多个值。

 

7.4 节展示了一个 Cfunction 的例子。

 

-------------------

5.6 错误处理

-------------------

当在 Lua 编译或执行时出现一个错误的时候,会调用一个查错程序,相应的 lua_dofile 或 lua_dostring 会中断并返回一个出错状态。

 

查错程序的唯一的一个参数就是一个字符串,它描述了出现的错误和一个额外的信息,像当前的行(当错误发生在编译时)或者当前的函数(当错误发生在运行时)。错误的查错程序只是打印这个信息到标准错误输出。如果需要的话,可以给它设置一个新的查错程序,用下面的函数:

void lua_errorfunction (void (*fn) (char *s));

它的参数是错误处理函数的地址。

 

--------------------------------------

6 预定义的函数和库

--------------------------------------

Lua 的一组预定义函数虽少但功能强大。他们中大多数提供的功能让语言有一定程度的自反性。这些功能不能通过语言的其它部分模拟也不能通过标准的 API 模拟。

 

库,在另一方面,提供了一种通过标准 API 实现的有用的程序。因此,它们并非语言必须的部分,并且作为单独的 C 模块被提供,它可以根据需要被连接到应用程序。

目前,有三个库:

字符串处理

数学函数(sin, cos, 等)

输入输出

 

预定义函数能处理以下任务:执行包含在一个文件或字符串中的 Lua 模块;遍历一个表的所有字段;枚举所有的全局变量;类型查询和转换。

 

-------------------

6.1 预定义函数

-------------------

dofile (filename)

函数接受一个函数名字,打开并执行它的内容做为一个 Lua 模块。它返回 1 如果没有出错,否则返回 0。

 

dostring (string)

函数执行一个给定的字符串做为一个 Lua 模块,没有错误返回 1, 否则返回 0。

 

next (table, index)

函数允许一个程序枚举一个表的所有字段。它的第一个参数是一个表,第二个参数是表中的索引;这个索引可以是数字或字符串。它返回表的下一个键值对(索引及和索引关联的值)。当用 nil 做为第二个参数调用它时,函数返回表的第一个健值对。当用最后一个索引调用,或者用 nil 调用一个空表,均返回 nil。

 

Lua 中没有字段的声明;在语义上,表中一个字段不存在和字段的值为 nil 没有区别。所以,该函数只考虑没有空值的字段。索引的枚举顺序没有规定,就算是数字索引的也没有规定。

 

7.1 节有一个使用这个函数的例子。

 

nextvar (name)

函数和 next 函数类似,但它在全局变量上遍历。它的参数是全局变量的名字,或者是 nil (可以获得第一个名字)。和 next 类似,它返回另一个变量的名字和值。或者是 nil 如果没有更多的变量了(遍历结束了)。

7.1 节 有一个使用这个函数的例子。

 

print (e1, e2, ...)

函数可以接受任意数量的参数,以一种合理的格式打印它们的值。每一个值都在一个新行上打印。这个函数不是为了格式化输出,只是为了以一种快速的方法显示一个值,例如打印一个出错信息或者调试。详见 6.4 节一个格式化输出函数。

 

tonumber (e)

函数接受一个参数,尝试把它转化为一个数字。如果参数已经是一个数字或者是一个可以转化为数字的字符串(详见 4.2 节),它返回那个数字;否则,返回 nil。

 

type (v)

函数允许 Lua 测试一个值的类型。它接受一个参数,返回它的类型,以一个字符串表示。这个函数可能的返回值是:

'nil'

'number'

'string'

'table'

'cfunction'

'function'

'userdata'

 

-------------------

6.2 字符串处理

-------------------

这个库提供字符串处理的通用函数,如查找和提取子串。索引一个字符串的时候,第一个字符的索引是 1。7.2 节有一些字符串处理的例子。

 

strfind (str, substr)

接受两个字符串参数,返回一个数字。这个数字标明第二个参数在第一个参数中第一次出现的位置。如果第二个参数不是第一个参数的子串,返回 nil。

 

strlen (s)

接受一个字符串返回它的长度。

 

strsub (s, i, j)

返回另一个字符串,它是 s 的子串,始于 i 终于 j 。 如果 j 不指定或者为 nil,它被假定为 s 的长度。特别的,strsub(s,1,j) 调用返回 s 的 j 个字符的前缀,strsub(s,i) 返回 s 的后缀。

 

strlower (s)

接受一个字符串,返回它的所有大写字母都转化为小写的拷贝。其它的字符保持不变。

 

strupper (s)

接受一个字符串,返回它的所有小写字母都转化为大写的拷贝。其它的字符保持不变。

 

-------------------

6.3 数学函数

-------------------

这个库到一些标准 C 函数库函数的一个接口。它提供了以下的函数:

abs acos asin atan ceil cos floor max min

mod pow sin sqrt tan

函数 floor, sqrt, pow, ceil, sin, cos, tan, asin, acos, 和 atan 只是到 C 函数库中同名函数的接口,不同之处是,在三角函数中,所有的角度被转化为弧度。

 

max 返回数字参数列表中的最大值,类似的,min 返回最小值。它们的参数个数都是任意的。

 

mode 和 C 语言中的 % 操作符是等价的。

 

-------------------

6.4 I/O

-------------------

Lua 中所有的 I/O 操作都是基于两个当前文件,一个是为了读,一个是为了写。当前的输入输出文件的初始值分别是 stdin, stdout。

除非特别规定,所有的 I/O 函数功能时返回 1 失败时返回 nil。

 

readfrom (filename)

函数打开一个名为 filename 的文件并且把它设置为当前的入出文件。当无参调用它时,这个函数把当前的输入文件恢复为 stdin。

 

writeto (filename)

函数打开一个名为 filename 的文件并且把它设置为当前的输出文件。注意,如果这个文件是已经存在,调用这个操作会清除它。当无参调用它时,这个函数把当前的输出文件恢复为 stdout。

 

appendto (filename)

函数打开一个名为 filename 的文件并且把它设置为当前的输出文件。不像 writeto 操作,这个函数不会清除文件之前的内容。当无参调用它时,这个函数把当前的输出文件恢复为 stdout。这个函数返回 2 如果文件已经存在,返回 1 如果新建了一个文件,返回 nil 如果失败。

 

read ([format])

函数返回从当前输入读取的值。一个可选的参数指定输入的解释方式。

 

如果没有格式化参数,read 首先跳过空白(空格,制表符,换行符)。然后它检查当前的字符是否是单引号或双引号(”,’)。如果是,它读取一个字符串直到字符串结束标志,并且返回这个字符串,不带字符串的标志符。否则,它读取直到另一个空白(空格,制表符,换行符)。

 

格式化字符串可以是以下的形式:

?[n]

? 可以是:

's' 或者 'S' 读一个字符串;

'f' 或者 'F' 读一个实数;

'i' 或者 'I' 读一个整数。

可选的 n 是一个数字指示为了构成输入而必须读取多少个字符。

 

write (value, [format])

函数写第一个参数的值到当前输出。可选的第二个参数指示使用格式。这个格式作为一个字符串给出,由四部分组成。第一个部分是必不少的,它必须是下面的几个字符之一:

's' 或者 'S' 写字符串;

'f' 或者 'F' 写实数;

'i' 或者 'I' 写整数。

这些字符可以后接:

[?][m][.n]

 

? 指示字段的对齐方式

'<' 右对齐

'>' 左对齐

'|' 居中对齐

 

m 指示字符的大小

 

.n 对于实数,指示小数点的位数。对于整数,它是最小位数。对于字符串此位无意义。

 

当这个函数调用没有给出格式字符串时,这个函数写数字使用 %g 格式,写字符串使用 %s 。

 

(未完待续)

posted @ 2015-11-05 14:48  vd01  阅读(359)  评论(0编辑  收藏  举报