本第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于更高版本,但存在一些差异。
第四版针对 Lua 5.3,可在 Amazon 及其他书店购买。
通过购买本书,您也为 支持 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, fmt, 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。保留所有权利。 | ![]() |