好久没有在网上留言了。。。

 

背景介绍

因为工作的需要,后台svr要能够动态修改更新,使用C当然没有问题,问题就在于修改源码后,需要重启服务。所以就想到在C里能够嵌入一种脚本,最好是和C无缝结合的。因此就想到使用到LUA,LUA的大名圈内人士应该早有耳闻,只不过一直没有机会接触。机缘巧合,有幸一见。

 

俗话说得好,耳闻不如一见。LUA使用起来还是很简单的,语法和普通的脚本语言相差不大,很容易上手。在实际项目的使用过程中,对LUA性能的体验也是感受尤深。这也是决定一探LUA源码的动力所在。因此,本笔记也只是针对LUA源码的相关记录,不会涉及到LUA使用上的一些问题。同时,也欢迎各位LUA爱好者批评指正笔记中的错误之处。废话不说了,切入正题。

 

(1)mathlib strlib

mathlib 和 strlib是lua的一个基本库,每个函数的实现都是在在基本库的基础上重新封装,举个例子

 

static int math_abs (lua_State *L) {
  lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
  return 1;
}

调用基本库fabs()函数,将返回的结果压栈返回。那肯定有一个疑问,就是参数怎么传递进去的?是呀,参数怎么传递进去的,我现在也不知道,但是不要紧,先有个印象就行。

还要明白一点,外界不会直接调用math_abs(),为什么?static呀,如果不明白的,先修炼一下C的基本功吧,下面继续来猜测外面怎么调用这些函数。

 

static const luaL_Reg mathlib[] = {
  {"abs",   math_abs},
  {"acos",  math_acos},
  {"asin",  math_asin},
  {"atan2", math_atan2},
  {"atan",  math_atan},
  {"ceil",  math_ceil},
  {"cosh",   math_cosh},
  {"cos",   math_cos},
  {"deg",   math_deg},
  {"exp",   math_exp},
  {"floor", math_floor},
  {"fmod",   math_fmod},
  {"frexp", math_frexp},
  {"ldexp", math_ldexp},
  {"log10", math_log10},
  {"log",   math_log},
  {"max",   math_max},
  {"min",   math_min},
  {"modf",   math_modf},
  {"pow",   math_pow},
  {"rad",   math_rad},
  {"random",     math_random},
  {"randomseed", math_randomseed},
  {"sinh",   math_sinh},
  {"sin",   math_sin},
  {"sqrt",  math_sqrt},
  {"tanh",   math_tanh},
  {"tan",   math_tan},
  {NULL, NULL}
};

上面这个结构体定义了内部函数名(或者是函数指针)与外部函数名之间的映射关系,比如要调用math_abs(),那实际使用的就是abs()来调用,目前,这还是猜测,是不是这样还有待验证。

那luaL_Reg 是啥,看如下声明:

typedef struct luaL_Reg {
  const char *name;
  lua_CFunction func;
} luaL_Reg;

就是一个名字,和一个函数指针,

typedef int (*lua_CFunction) (lua_State *L);

lua如何将这个映射注册进去呢,看下面的函数,这个是mathlib的外部唯一接口

LUALIB_API int luaopen_math (lua_State *L) {
  luaL_register(L, LUA_MATHLIBNAME, mathlib);
  lua_pushnumber(L, PI);
  lua_setfield(L, -2, "pi");
  lua_pushnumber(L, HUGE_VAL);
  lua_setfield(L, -2, "huge");
#if defined(LUA_COMPAT_MOD)
  lua_getfield(L, -1, "fmod");
  lua_setfield(L, -2, "mod");
#endif
  return 1;
}

大概的意思就是将mathlib这个luaL_Reg对象在L中注册登记,L是什么,L就是lua_State*!!!!!等于没说,但是目前的认知也就是这些,这是最准确的表述,不是吗?从名字上看,应该是一个状态机。想知道到底是什么,接着看代码。注册登记完了,将一些常量压栈。应该是设置一些环境变量,等等。

 

strlib和mathlib的结构差不多,

也是重新封装一大堆函数,然后通过一个唯一接口来注册所有的函数。实际使用的时候,也就是调用这个唯一的接口。调用完该接口,应该就可以在那个叫做lua_State*的L中使用这些基本库函数了。

 

到目前为止,很多还是不确定的,比如lua_State是什么,为什么基本库的注册登记,都要向针对这个L进行。L中到底维护的是什么信息,翻开lua_State的定义,一大堆数据,很多都不知道是什么。好吧,先不看这个,先继续看别的,但是要知道这个就是一个结构体就行,这个结构体里面肯定维护很多核心的东西。