Luaconf.h是配置的总集, 定义了平台相关的设置,是所有文件都包含的,即Rootly Included。
0. 前言
开始关注Lua也是06年六月的事情,《程序员》的2006年第六期中,我独独看中了Lua,而不是当时我已经
比较熟悉的Python和Ruby,即使它们我都关注了好几年,但是都没有Lua给我的震撼大。于是那个夏天,
稍微地尝试读了Lua的代码。
开学后,我突然觉得自己有点受唆使,轻信了动态的福音,对Lisp系以及脚本系关注太多,有点不务正业
,于是回到了C,并且在年底投入了C++。C++的模板实在是让我爱不释手,于是寒假的时候写了一个内存
分配器,用了很多模板技巧,于是渐渐地对C++也熟悉了。
到了下学期,也就是现在,经历了一个小项目之后,在放弃C++/CLI的福音转向C#后,在.NET的信仰下,
在对DLR的期待中,决心写一个Lua的DLR实现,于是我回来了。
1. 基础设施代码解读
这部分包括基本数据结构,内存管理等部分,是重头戏。
1.1. 基本数据结构
正如Brooks所说“给我看你的流程图而藏起你的表,我将仍然莫名其妙。如果给我看你的表,那么我将不
再要你的流程图,因为它们太明显了。”不理解Lua最基本的数据结构,想要理解Lua是完全不可能的。
我们从包含的Root项,即Luaconf.h开始,它给出了最基本的信息。它是基于编译器和平台,对Lua进行最
基本的设置,是程序的元数据区。
第一段,平台选择:
/*
** LUA_ANSI控制对non-ansi字符集特性的使用。
** 定义这个宏,你可以不使用non-ansi特性的使用。
*/
#if defined(__STRICT_ANSI__)
#define LUA_ANSI
#endif
#if !defined(LUA_ANSI) && defined(_WIN32)
#define LUA_WIN
#endif
#if defined(LUA_USE_LINUX)
#define LUA_USE_POSIX
#define LUA_USE_DLOPEN /* 需要额外的库: -ldl */
#define LUA_USE_READLINE /* 需要一些额外的库 */
#endif
#if defined(LUA_USE_MACOSX)
#define LUA_USE_POSIX
#define LUA_DL_DYLD /* 不需要额外的库 */
#endif
显然对于LUA_WIN来说,w32平台的确是用Unicode的,也就是非LUA_ANSI的。当定义了LUA_USE_LINUX和
LUA_USE_MACOSX后,需要POSIX标准以及定义相应的打开动态链接库的方法。这里可以看出Linux和BSD系
在打开动态库时的差别。
这里是POSIX的相关定义:
/*
** LUA_USE_POSIX包含了所有被标注为X/Open系统接口扩展(XSI)的功能。
** 如果你的系统兼容XSI,则定义它。
*/
#if defined(LUA_USE_POSIX)
#define LUA_USE_MKSTEMP
#define LUA_USE_ISATTY
#define LUA_USE_POPEN
#define LUA_USE_ULONGJMP
#endif
这个是环境变量相关的:
/*
** LUA_PATH和LUA_CPATH是Lua设置自己路径的环境变量名字。
** LUA_INIT是Lua检查初始化代码的环境变量名字。
** 如果你要更改名字,则自己定义。
*/
#define LUA_PATH "LUA_PATH"
#define LUA_CPATH "LUA_CPATH"
#define LUA_INIT "LUA_INIT"
具体路径自己定。
于是这一段也很好理解了:
/*
** LUA_PATH_DEFAULT是Lua默认的搜索Lua库的路径。
** LUA_CPATH_DEFAULT是Lua默认的搜索C库的路径。
** 如果你的机器是非传统的目录体系结构或者你要把你的库装入非传统的目录体系结构中则更改它们。
*/
#if defined(_WIN32)
/*
** 在Windows中,出现在路径中的惊叹号('!')将由当前进程的可执行文件所在的目录的路径替换
*/
#define LUA_LDIR "!//lua//"
#define LUA_CDIR "!//"
#define LUA_PATH_DEFAULT /
".//?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?//init.lua;" /
LUA_CDIR"?.lua;" LUA_CDIR"?//init.lua"
#define LUA_CPATH_DEFAULT /
".//?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
#else
#define LUA_ROOT "/usr/local/"
#define LUA_LDIR LUA_ROOT "share/lua/5.1/"
#define LUA_CDIR LUA_ROOT "lib/lua/5.1/"
#define LUA_PATH_DEFAULT /
"./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" /
LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua"
#define LUA_CPATH_DEFAULT /
"./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so"
#endif
好了,接下来是Lua中特别指明的平台相关部分,库的加载:
/*
** LUA_API是所有核心API的标记。
** LUALIB_API是所有标准库函数的标记。
** 如果你对函数有特殊的要求请更改它们。
** 比如你要定义一个w32 DLL要要用到核心和库函数,你可能会用到下面的LUA_BUILD_AS_DLL定义。
*/
#if defined(LUA_BUILD_AS_DLL)
#if defined(LUA_CORE) || defined(LUA_LIB)
#define LUA_API __declspec(dllexport)
#else
#define LUA_API __declspec(dllimport)
#endif
#else
#define LUA_API extern
#endif
/* 库时常和核心一起发布 */
#define LUALIB_API LUA_API
这里的LUA_BUILD_AS_DLL就是在编译的时候提交给编译器的一个选项。下面是另外一些自定义关键字。
/*
** LUAI_FUNC是那些不要导出模块外部的extern函数。
** LUAI_DATA是那些不要导出的extern或者扩展的变量。
** 当你对它们有特殊的要求时请改变他们。当Lua被编译为共享库时,Elf/gcc(3.2或更高版本