第一版是针对 Lua 5.0 编写的。虽然在很大程度上仍然适用于后续版本,但有一些不同之处。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还将帮助 支持 Lua 项目。
用 Lua 编程 | ||
第四部分。C API 第 24 章。C API 概述 |
我们将从一个应用程序的简单示例开始此概述:一个独立的 Lua 解释器。我们可以按如下方式编写一个原始的独立解释器
警告:此代码适用于 Lua 5.0。要在 Lua 5.1 中运行它,您必须将五个调用 luaopen_*(L)
更改为对 luaL_openlibs(L)
的一次调用。
#include <stdio.h> #include <string.h> #include <lua.h> #include <lauxlib.h> #include <lualib.h> int main (void) { char buff[256]; int error; lua_State *L = lua_open(); /* opens Lua */ luaopen_base(L); /* opens the basic library */ luaopen_table(L); /* opens the table library */ luaopen_io(L); /* opens the I/O library */ luaopen_string(L); /* opens the string lib. */ luaopen_math(L); /* opens the math lib. */ while (fgets(buff, sizeof(buff), stdin) != NULL) { error = luaL_loadbuffer(L, buff, strlen(buff), "line") || lua_pcall(L, 0, 0, 0); if (error) { fprintf(stderr, "%s", lua_tostring(L, -1)); lua_pop(L, 1); /* pop error message from the stack */ } } lua_close(L); return 0; }头文件
lua.h
定义了 Lua 提供的基本函数。其中包括创建新 Lua 环境(例如 lua_open
)、调用 Lua 函数(例如 lua_pcall
)、读取和写入 Lua 环境中的全局变量、注册由 Lua 调用的新函数等。lua.h
中定义的所有内容都带有 lua_
前缀。
头文件 lauxlib.h
定义了辅助库(auxlib)提供的函数。其所有定义均以 luaL_
开头(例如 luaL_loadbuffer
)。辅助库使用 lua.h
提供的基本 API 来提供更高的抽象级别;所有 Lua 标准库都使用 auxlib。基本 API 追求经济性和正交性,而 auxlib 则追求常见任务的实用性。当然,您的程序也可以非常轻松地创建它需要的其他抽象。请记住,auxlib 无法访问 Lua 的内部。它通过官方基本 API 完成其所有工作。
Lua 库根本不定义任何全局变量。它将所有状态保存在动态结构 lua_State
中,并且指向此结构的指针作为参数传递给 Lua 中的所有函数。此实现使 Lua 可重入并可用于多线程代码。
lua_open
函数创建一个新环境(或状态)。当 lua_open
创建一个新环境时,此环境不包含任何预定义函数,甚至不包含 print
。为了保持 Lua 的精简,所有标准库都作为单独的包提供,这样您不必在不需要时使用它们。头文件 lualib.h
定义了用于打开库的函数。例如,对 luaopen_io
的调用会创建 io
表并在此表中注册 I/O 函数(io.read
、io.write
等)。
在创建状态并使用标准库填充它之后,是时候解释用户输入了。对于用户输入的每一行,程序首先调用 luaL_loadbuffer
来编译代码。如果没有错误,该调用将返回零并将结果块推入堆栈。(请记住,我们将在下一节中详细讨论这个“神奇”堆栈。)然后,程序调用 lua_pcall
,该调用从堆栈中弹出块并在受保护模式下运行它。与 luaL_loadbuffer
类似,如果不存在错误,lua_pcall
将返回零。如果出现错误,这两个函数都会将错误消息推入堆栈;我们使用 lua_tostring
获取此消息,并在打印它之后,使用 lua_pop
将其从堆栈中删除。
请注意,如果出现错误,此程序只会将错误消息打印到标准错误流。真正的错误处理在 C 中可能非常复杂,具体方法取决于应用程序的性质。Lua 核心从不直接将任何内容写入任何输出流;它通过返回错误代码和错误消息来发出错误信号。每个应用程序都可以以最适合其需求的方式处理这些信号。为了简化我们的讨论,我们现在将假设一个简单的错误处理程序,如下所示,它将打印错误消息、关闭 Lua 状态并退出整个应用程序
#include <stdarg.h> #include <stdio.h> #include <stdlib.h> void error (lua_State *L, const char *fmt, ...) { va_list argp; va_start(argp, fmt); vfprintf(stderr, argp); va_end(argp); lua_close(L); exit(EXIT_FAILURE); }稍后,我们将进一步讨论应用程序代码中的错误处理。
由于您可以将 Lua 同时编译为 C 代码和 C++ 代码,因此 lua.h
不包含其他几个 C 库中存在的这种典型的调整代码
#ifdef __cplusplus extern "C" { #endif ... #ifdef __cplusplus } #endif因此,如果您已将 Lua 编译为 C 代码(最常见的情况)并在 C++ 中使用它,则必须按如下方式包含
lua.h
extern "C" { #include <lua.h> }一个常见的技巧是创建一个包含上述代码的头文件
lua.hpp
,并在 C++ 程序中包含此新文件。
版权所有 © 2003–2004 Roberto Ierusalimschy。保留所有权利。 |