Lua2.4 参考手册(三)

(接上篇)
--------------------------------------
5 API
--------------------------------------
这节主要描述 Lua 的 API, 也就是宿主程序和库交互的一组 C 函数。API 函数可以分为以下几类:
1. 执行 Lua 代码;
2. 在 Lua 和 C 之间进行值的转化;
3. 操作(读写)Lua 对象;
4. 调用 Lua 函数;
5. 由 Lua 调用的 C 函数;
6. Lua 对象的引用。

所有的 API 都在文件 lua.h 中声明。

-------------------
5.1 执行 Lua 代码
-------------------
一个宿主程序可以执行写在文件中或在字符串中的 Lua 模块,使用下面的函数:
int lua_dofile (char *filename);
int lua_dostring (char *string);
两个函数都返回一个错误码:0 表示成功,非 0 表示失败。函数 lua_dofile,如果调用的时候参数为 NULL(0),将把标准输入作为“文件”执行。lua_dofile 也能执行预编译的模块。它能检查出文件是否是文本,并相应有加载它 (参见程序 luac)。

-------------------
5.2 在 Lua 和 C 之间进行值的转化
-------------------
因为 Lua 没有静态的类型系统,所有的在 Lua 和 C 之间传递的值的类型为 lua_Object,它像是 C 中的可保存任何 Lua 值的一个抽象的类型。 lua_Object 类型的在 Lua 之外是没有意义的,例如,比较两个 lua_Object 就没有意义。

Lua 有自动内存管理和垃圾回收。因此,一个 lua_Object 有一个受限的作用域,它只在新建它的块(block)中有效。一个从 Lua 调用的 C 函数是一个 block,它的参数只在它结束之前是有效的。一个好的编程实践是在这些值(Lua 对象)可用的时候把它转化为 C 语言的值,并且永远不要把 lua_Object 保存在 C 全局变量中。

当一个 C 代码频繁的调用 Lua 代码的时候,比如在一个循环中,这些返回的对象一直累积,可能会带来内存问题。为了避免这种情况,嵌套的块可以在下面的函数中定义:
void lua_beginblock (void);
void lua_endblock (void);
块结束之后,所有在它之中新建的 lua_Object 都会被释放。

可以使用下面的函数来检查一个 lua_Obejct 的类型:
int lua_type (lua_Object object);
还有下面的这些宏和函数:
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_isfunction (lua_Object object);
int lua_iscfunction (lua_Object object);
int lua_isuserdata (lua_Object object);
所有宏返回 1 如果对象和给定类型兼容的话,否则返回 0。函数 lua_isnumber 可以接受数值和可转化为数值的字符串,lua_isstring 接受字符串和数值(参见 4.2 节),lua_isfunction 接受 Lua 和 C 函数。
lua_type 函数可以用来区分不同类型的用户数据,见下文。

可以使用下面的函数把一个 lua_Object 转化为 C 类型:
double 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 有垃圾回收,没有什么保证这个指针在 block 结束之后依然有效。

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

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

相反,把一个 C 类型转化为 lua_Obejct 类型用以下的函数:
void lua_pushnumber (double n);
void lua_pushstring (char *s);
void lua_pushcfunction (lua_CFunction f);
void lua_pushusertag (void *u, int tag);
还有一个宏:
void lua_pushuserdata (void *u);
这些函数都接受一个 C 值,把它转化为相应的 lua_Object,并把结果保存在 Lua 栈顶,在那里它可以被赋值给一个 Lua 变量,做为参数传递给一个 Lua 函数,等(见下文)。
用户数据(user data)可以有不同的标签(tag),它们的语义由宿主程序定义。任何正整数可以做为一个用户数据的标签。当一个用户数据返回的时候,可以使用 lua_type 来返回它的标签。

为了完成设置,nil 或者 lua_Object 也可以压栈,用下面的函数:
void lua_pushnil (void);
void lua_pushobject (lua_Object object);

-------------------
5.3 操作Lua 对象
-------------------
可以使用以下的函数读取 Lua 全局变量的值:
lua_Object lua_getglobal (char *varname);
在 Lua 中,如果全局变量的值为 nil, 回退函数 “getglobal" 会被调用。

把前先压到栈顶的一个值保存到一个全局变量,用下面的函数:
void lua_storeglobal (char *varname);

表也可以通过 API 来操作,函数:
lua_Object lua_getsubscript (void);
期望栈上是一个表和一个索引,并且返回表在索引处的内容。在 Lua 中,如果第一个对象不是一个表,或者索引在表中不存在,相应的回退函数会被调用。
为了保存一个值到给定的索引,程序必须把表,索引,值压栈,之后调用函数:
void lua_storesubscript (void);
相应的回退函数会被调用,如果需要的话。

最后,函数
lua_Object lua_createtable (void);
新建一个表。

请注意:大部分 Lua 库中的函数从栈上接受参数。因为其它的函数也使用这个相同的栈,所以在调用函数前参数压栈时请务必保证不调用 Lua 库中的函数。例如:如果用户想获得 a[i] 的值,一个单纯的解决方案是:
/* Warning: WRONG CODE */
lua_Object result;
lua_pushobject(lua_getglobal("a")); /*push table*/
lua_pushobject(lua_getglobal("i")); /*push index*/
result = luat_getsubscript();
然而,lua_getglobal("i") 调用改变了栈,使先前压栈的值无效了。一个正确的解决方案是:
lua_Object result;
lua_Object index = lua_getglobal("i");
lua_pushobject(lua_getglobal("a")); /*push table*/
lua_pushobject(index);                 /*push index*/
result = luat_getsubscript();

-------------------
5.4 调用 Lua 函数
-------------------
在宿主程序中可以调用由模块执行 dofile 或者 dostring 定义的函数。这采用如下的协议:首先,函数参数压到 Lua 栈上(参见 5.2 节),压栈的顺序和参数一致,也就是第一个参数首先压栈。再次强调,在压栈过程中,不要调用其它的 Lua 函数。
然后,函数调用可以用:
int lua_call (char *functionname);
或者
int lua_callfunction (lua_Object function);
两个函数都返回一个错误码:0 表示成功,非 0 表示失败。最后,返回值(Lua 函数可以返回多个值)可以用下面的宏取得:
lua_Object lua_getresult (int number);
number 就是返回的结果的顺序,从 1 开始。当用一个大于实际返回结果数的数值调用时,这个函数返回 LUA_NOOBJECT.
两个特殊的 Lua 函数有特殊的作用:error 和 setfallback。一个 C 函数可以产生一个 Lua 错误通过调用函数:
void lua_error (char *message);
这个函数不返回。如果在 Lua 里调用这个 C 函数,相应在的 Lua 执行就被终结了,如同在 Lua 代码中发生一个错误。否则,整个程序结束。

回退函数可以通过下面的函数修改:
lua_Object lua_setfallback(char *name, lua_CFunction fallback);
第一个参数是回退的名字,第二个是一个将做为新的回退函数的 CFunction。这个函数返回老的回退函数 lua_Object,或者失败时返回 nil(无效的回退函数名字)。这个老的回退函数值可用来串连(chaining)回退函数。
8.10 节有一个 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 开始返回第一个参数。当用一个大于参数实际个数的值来调用时,该函数返回 LUA_NOOBJECT。用这种方法,就可以写可变参数个数的函数。
为了从 C 返回值到 Lua, C 函数可以把返回值顺序压栈;见 5.2 节。就像 Lua 函数一样,一个由 Lua 调用的 C 函数也可以返回多个值。

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

-------------------
5.6 Lua 对象的引用
-------------------
如前所述,lua_Object 是易变的(volatile)。如果一个 C 代码需要在块作用域以外保存一个 lua_Object 的话, 它必须新建一个对象的引用。下面的函数可以管理这种引用:
int lua_ref (int lock);
lua_Object lua_getref (int ref);
void lua_pushref (int ref);
void lua_unref (int ref);
函数 lua_ref 新建一个栈顶对象的引用,并返回这个引用。如果 lock 是 ture 的话,对象就被锁定:这意味着这个对象将不会被垃圾回收。注意一个没有锁定的引用可能会被垃圾回收。任何需要对象引用的地方都可以调用 lua_getref 来返回一个对象的句柄.lua_pushref 把对象压栈。如果对象已经被垃圾回收了,lua_getref 返回一个 LUA_NOOBJECT, lua_pushobject 会出错。
如果一个引用已经没用了,可以使用 lua_unref 调用来释放它。
(未完待续)

时间: 2024-11-09 17:23:08

Lua2.4 参考手册(三)的相关文章

Lua2.4 参考手册(一)

说明:这个文档是 Lua2.4 的 doc 目录里的 refman.ps 文件.原文版权归原作者所有,这篇翻译只是作为学习之用.如果翻译有不当之处,请参考原文.-------------------以下是正文-------------------编程语言 Lua2.4 的参考手册 摘要:Lua 是一个扩展程序语言,被设计用做其它程序的配置语言.本文档描述 Lua 编程语言 2.4 版,以及 Lua 程序和宿主 C 程序交互的 API.它还提供了一些使用这些主要特点的例子. -----------

Ogre参考手册(三)3.1.3 纹理单元TextureUnit

3.1.3 Texture Units 纹理单元 纹理单元通过.material脚本中的texture_unit段设定 texture_alias 设置纹理单元别名,例: texture_unit Diffuse //纹理单元名称 { texture_alias           DiffuseMap //别名 tex_address_mode  clamp } texture 设置纹理层使用的静态纹理图 格式:texture <texturefile> [<type>[unli

Lua2.4 参考手册(五)

(接上篇)--------------------------------------7 调试接口--------------------------------------Lua 没有内置的调试功能.而是借助于函数和钩子(hook)提供了一个特殊接口,可以用来构建不同种类的调试器,分析器(profile)和一些其它的需要解释器内部信息的工具.这个接口在 luadebug.h 文件中声明.-------------------7.1 栈和函数信息-------------------获得解释器栈

Lua2.4 参考手册(四)

(接上篇)--------------------------------------6 预定义的函数和库--------------------------------------Lua 的一组预定义函数虽少但功能强大.他们中大多数提供的功能让语言有一定程度的自反性.一些功能不能通过语言的其它部分模拟也不能通过标准的 Lua API 模拟.其它的只是一些有用的有用通用 API 函数接口. 库,在另一方面,提供了一种通过标准 API 实现的有用的程序.因此,它们并非语言必需的部分,并且作为单独的

Lua2.4 参考手册(二)

(接上篇)--------------------------------------4 语言--------------------------------------这节介绍 Lua 的词法,语法和语义. -------------------4.1 词法约定-------------------Lua 是区别大小写的语言.标识符可以是任何字母,数字,下划线组成的字符串,且首字母不可为数字.下面这些是保留的关键字,不可用做标识符:and     do     else     elseif 

Lua2.4 参考手册(六)

(接上篇)--------------------------------------8 一些例子--------------------------------------本段给出一些显示 Lua 特性的例子.它并不打算覆盖完整的语言,只是显示一有趣的使用. -------------------8.1 数据结构-------------------表是统一的数据结构.它可以实现多种数据类型,像通常的数组,记录,集合,包,和列表.数组不用解释.在 Lua 中,索引通常从 1 开始,但这只是个惯

bash参考手册之五(shell变量)续三

LINENO 当前在执行的脚本或者shell函数的行号. LINES 命令select用来确定打印选择列表的列宽.收到SIGWINCH后,自动设置. MACHTYPE 是一个字符串,描述了正在运行Bash的系统的类型,描述的格式符合GNU cpu-company-system 标准. MAILCHECK 确定多长时间间隔(以秒为单位),shell要去由变量MAILPATH和MAIL的值指定的文件中,检查邮件.默认值是60秒.当检查邮件的时间到了,shell在显示提示符前执行检查动作.如果这个变量

参考手册目录__第三部分

参考手册目录__第一部分 参考手册目录__第二部分 参考手册目录__第三部分 第 26 章: 扩展与嵌入Python 26.1 扩展模块------482  26.1.1 扩展模块原型------484 26.1.2 命名扩展模块------486 26.1.3 编译与打包扩展------486 26.1.4 从Python 到 C 语言的类型转换------488 26.1.5 从C 到 Python 的类型转换------492 26.1.6 给模块添加值------493 26.1.7 错

KnockoutJS 3.X API 第三章 计算监控属性(5) 参考手册

计算监控属性构造参考 计算监控属性可使用以下形式进行构造: ko.computed( evaluator [, targetObject, options] ) - 这种形式是创建一个计算监控属性最常见的情况. evaluator - 用于返回计算值的函数. targetObject-如果给出定义的值this时KO调用回调函数.参见部分第三章 计算监控属性(1) 使用计算监控属性以获取更多信息. options - 计算监控属性的其他属性的对象.请参见下面的完整列表. ko.computed(