手把手教你成功编译《Lua 程序设计》书中第24章简化版Lua解释器的例子

  • 作者: FreeBlues
  • 修订版本: 1.00


很多人都看过《Lua 程序设计》 这本书, 在 第24章 C API 概述 中, 提供了一个非常简单的 Lua 解释器的例子, 如下:

24.1 第一个示例 将通过一个简单的 Lua 解释器程序来开始 C API 的学习. 以下代码就是一个最原始的解释器程序:

#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 = luaL_newstate();
        luaL_openlibs(L);

        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);
                }
        }

        lua_close(L);
        return 0;
}

就是这段代码, 可是当你把它原样照抄, 却发现怎么也没办法顺利地把它成功编译.

一般来说, 初学者都是这样开始的:

  • 新建一个 Lua 文件, 比如 myLua.c, 把上述代码拷贝进去;
  • lua.org 下载源码, 解压, 把其中的 lua.c, lua.h, lauxlib.c, lauxlib.h, lualib.c, lualib.h 拷贝到新建文件 myLua.c 所在的目录下(可能在源码中找不到 lualib.c 这个文件, 先不管那么多, 把源码中所有的 .c 文件和 .h 文件全部拷贝过来, 试试再说);
  • 执行 gcc myluac.c.

这时通常会返回错误, 提示说找不到这个找不到那个, 于是初学者就失败了, 那么究竟是什么原因导致编译失败呢?

其实, 主要还是作者在这里没有把操作细节交代清楚, 而不少初学者对于 C 的编译一知半解, 尤其在涉及到共享库(包括静态库和动态库)的编译和使用时更是如此.

具体来说, 这里需要先根据 Lua 源码把 lua.c 编译成一个静态共享库 liblua.a, 然后再在编译我们的简化版的解释器时把这个静态共享库链接进去, 头文件 liblua.h 就是它的, 这样才可以顺利完成编译.

具体操作如下:

  1. 首先, 要把 Lua 编译成静态库的形式, 从 Lua 官网下载回源码, 解压, 然后执行如下编译命令:
make macosx

说明: 我使用的环节是 MacOSX, 所以加了参数 macosx, 你可以根据自己的平台选择不同的参数, 有这么一些参数可选 aix bsd c89 freebsd generic linux macosx mingw posix solaris

这里因为 Lua 官方源码的 Makefile 文件默认会编译为静态共享库, 所以在 src 目录你会得到一个静态库文件 liblua.a:

Air:src admin$ ls -al liblua.a 
-rw-r--r--  1 admin  staff  342264  7 20 18:12 liblua.a
Air:src admin$
  1. 其次, 要把刚才编译好的静态库 liblua.a 拷贝到你 myLua.c 所在的目录;
  2. 最后编译时要在命令行中设置 3 个编译参数:
  • 参数 -L. 指定库文件在当前目录 .
  • 参数 -llua 指定库名称为 lua(库名称不需要加 lib);
  • 参数 I./lua-src/5.3/ 指定 include 文件(这里就是 .h 头文件)目录在 ./lua-src/5.3/
  1. 然后就可以顺利编译了, 完整的编译命令如下:
gcc mylua.c -L. -llua -I./lua-src/5.3/ -o mylua

这样就终于成功完成编译了, 操作记录如下:

Air:lua+c admin$ gcc mylua.c -L. -llua -I./lua-src/5.3/ -o mylua
Air:lua+c admin$ ls
liblua.a	lua-src		mylua		mylua.c
Air:lua+c admin$ ls -al
total 1120
drwxr-xr-x   6 admin  staff     204  8 15 23:54 .
drwxr-xr-x  19 admin  staff     646  7 23 17:54 ..
-rw-r--r--   1 admin  staff  342264  8 15 23:54 liblua.a
drwxr-xr-x   4 admin  staff     136  7 20 17:36 lua-src
-rwxr-xr-x   1 admin  staff  221320  8 15 23:54 mylua
-rw-r--r--   1 admin  staff     447  7 20 21:48 mylua.c
Air:lua+c admin$

执行一下我们编译的这个简化版的 Lua 解释器:

Air:lua+c admin$ ./mylua 
print("hello world!")
hello world!
print(12+23)
35
p = {}

OK, 至此大功告成!