Lua源码阅读:标准库

Lua标准库中定义的一些函数及其实现方式。

lmathlib.c

从一个简单的math.Abs()函数开始:

1
2
3
4
5
6
7
8
9
10
static int math_abs (lua_State *L) {
if (lua_isinteger(L, 1)) {
lua_Integer n = lua_tointeger(L, 1);
if (n < 0) n = (lua_Integer)(0u - n);
lua_pushinteger(L, n);
}
else
lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1)));
return 1;
}

首先,先检查传入的值是否是int类型,这里调用了lapi.c中的lua_isinteger函数,检查传入值的TValue原始类型标签是否是LUA_TNUMINT,这部分的检查在lObject.h中定义的函数完成,同时数据类型LUA_TNUMINT也在lObject.h中定义:

1
2
3
4
5
/* Variant tags for numbers */
#define LUA_TNUMFLT (LUA_TNUMBER | (0 << 4)) /* float numbers */
#define LUA_TNUMINT (LUA_TNUMBER | (1 << 4)) /* integer numbers */

// lObject.h

如果传入的值的TValue是int类型的(传入的值是lua_state类型的),调用lua_tointeger将传入的值转换为int类型(实际上是lua_Integer类型,其最根源是longlong类型的,在luaconf.h中定义),将其赋给n,如果n小于零,则用一个unsigned 0减去它,将其置为正数,最后将n存入到TValue中,将其存放在lua_state的栈顶。

如果不是int类型的,则检查其是否是一个number类型的值,如果是一个number则调用fabs,将其push栈,否则返回一个错误提示。

lstrlib.c

strlib中一部分是关于字符串的操作函数,一部分是关于模式匹配的函数,先挑选一个Reverse函数进行分析:

1
2
3
4
5
6
7
8
9
10
static int str_reverse (lua_State *L) {
size_t l, i;
luaL_Buffer b;
const char *s = luaL_checklstring(L, 1, &l);
char *p = luaL_buffinitsize(L, &b, l);
for (i = 0; i < l; i++)
p[i] = s[l - i - 1];
luaL_pushresultsize(&b, l);
return 1;
}

简单来说就是利用一个指针(index)来对字符数组进行逆序的赋值,从数组s中获取赋值给数组p。