版本整理日期:2011/3/27
对lmathlib.c文件中的函数进行跟调。函数是那个不重要,这里选取math_abs
/*
lmathlib.c
取出一个TValue,转成整型,然后fabs处理。TValue可能是字符串,也可能就是数字。
luaL_checknumber的行为是必返回一个number值
lua_pushnumber的行为是把结果进行压栈处理,具体怎么处理还不知道
return 1;表示参数个数。有做过lua和c交互的就很熟悉了,表示结果的个数
可以得到的信息是,lua通过push参数+个数来表示结果的传递
*/
static int math_abs (lua_State *L) {
//luaL_checknumber 见1.1
//lua_pushnumber见1.2
lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));
return 1;
}
/*
1.1
lauxlib.c
调用lua_tonumber,并且对参数进行一个检测,可以看成是一个辅助性的函数
*/
LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
//lua_tonumber见1.1.1
lua_Number d = lua_tonumber(L, narg);
if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
tag_error(L, narg, LUA_TNUMBER);
return d;
}
/*
1.1.1
lapi.c
观察是怎么取出一个值的.其中index2adr,tonumber等都是很常见的函数,
不做单独的段落分析,统一放在末尾一起分析
*/
lua_tonumber()
{
//从栈上取出一个TValue变量
const TValue *o = index2adr(L, idx);
//一个宏转换,是否是number类型
if (tonumber(o, &n))
//从TValue里取出值
return nvalue(o);
else
//失败返回0
return 0;
}
/*
1.1.1宏整理
都用到了以下这些宏
*/
//lobject.h
#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
//lvm.h
#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \
(((o) = luaV_tonumber(o,n)) != NULL))
这些宏都是对TValue进行操作,来看TValue结构,可以得到的信息是
1)TValue是lua通用的描述数据元的结构体
2)里面是通过tt来区分类型
3)typedef union Value里面,根据不同类型需要存放的对应变量
/*
** Union of all Lua values
*/
typedef union {
//gc先不管它
GCObject *gc;
//存放字符型空间
void *p;
//值double型
lua_Number n;
int b;
} Value;
//tt:值类型
#define TValuefields Value value; int tt
typedef struct lua_TValue {
TValuefields;
} TValue;
再回头看上面的宏,要注意的是tonumber,会先判断是否是LUA_TNUMBER,然后再进行转换。
我们跟踪下luaV_tonumber
/*
lvm.c
*/
const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
lua_Number num;
//判断是否数字型
//如果是字符型进行转换
if (ttisnumber(obj)) return obj;
//一个V值的转换,svalue表示取出字符串的char*空间
if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {
setnvalue(n, num);
return n;
}
else
return NULL;
}
//先整理下用到的宏
//lobject.h
//根据里面的tt类型来判断,还有诸如很多的判断字符串,表格等
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
//返回字符串空间,其中的层次组织很值得学习。raw->get->svalue
#define svalue(o) getstr(rawtsvalue(o))
#define getstr(ts) cast(const char *, (ts) + 1)
#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
//也是经常遇到的宏之一,包括一些对象的互相赋值等
#define setnvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
//lobject.h
//该函数主要就是调用了C标准函数库
int luaO_str2d (const char *s, lua_Number *result) {
char *endptr;
//luaconf.h, #define lua_str2number(s,p) strtod((s), (p)), strtod,C函数库
*result = lua_str2number(s, &endptr);
if (endptr == s) return 0; /* conversion failed */
if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
*result = cast_num(strtoul(s, &endptr, 16));
if (*endptr == '\0') return 1; /* most common case */
while (isspace(cast(unsigned char, *endptr))) endptr++;
if (*endptr != '\0') return 0; /* invalid trailing characters? */
return 1;
}
//limits.h
//cast转换函数,也是经常用到的
#ifndef cast
#define cast(t, exp) ((t)(exp))
#endif
#define cast_byte(i) cast(lu_byte, (i))
#define cast_num(i) cast(lua_Number, (i))
#define cast_int(i) cast(int, (i))
/*
1.2
lapi.c
lua_pushnumber
*/
LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
lua_lock(L);
setnvalue(L->top, n);
api_incr_top(L);
lua_unlock(L);
}
//lobject.h
#define setnvalue(obj,x) \
{ TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }
这里对L->top很感兴趣,结合index2adr一起分析下
//lapi.c
static TValue *index2adr (lua_State *L, int idx) {
if (idx > 0) {
TValue *o = L->base + (idx - 1);
api_check(L, idx <= L->ci->top - L->base);
if (o >= L->top) return cast(TValue *, luaO_nilobject);
else return o;
}
else if (idx > LUA_REGISTRYINDEX) {
api_check(L, idx != 0 && -idx <= L->top - L->base);
return L->top + idx;
}
else switch (idx) { /* pseudo-indices */
case LUA_REGISTRYINDEX: return registry(L);
case LUA_ENVIRONINDEX: {
Closure *func = curr_func(L);
sethvalue(L, &L->env, func->c.env);
return &L->env;
}
case LUA_GLOBALSINDEX: return gt(L);
default: {
Closure *func = curr_func(L);
idx = LUA_GLOBALSINDEX - idx;
return (idx <= func->c.nupvalues)
? &func->c.upvalue[idx-1]
: cast(TValue *, luaO_nilobject);
}
}
}
先不具体去追究里面意思,可以知道这么几个信息
1)根据idx不同,可以取到不同的目标,而且idx可以是全局的
2)top其实是个连续的栈信息
3)L->ci似乎是个监测边界的东西
4)Closure的东西,有其他的存储方式
OK,到这,起码可以了解lua库的调用流程和思考方式习惯,再把各个调用函数对应的文件流程
整理下:
lmathlib.c(math_abs)
lauxlib.c(luaL_checknumber)
lapi.c(lua_tonumber,lua_isnumber)
lapi.c(index2adr)
lvm.h(tonumber)
lvm.h(luaV_tonumber)
lobject.h(luaO_str2d)
luaconf.h(lua_str2number)
可以得到如下信息:
1)luaX_,X可以表示lvm,lobject等
2)api.c表示lua内部的函数,lib库是对外开放的
3)lobject.h,luaconf.h是最基础的结构文件
分享到:
相关推荐
所有版本LUA源码 lua-5.3.5 lua-5.3.4 lua-5.3.3 lua-5.3.2 lua-5.3.1 lua-5.3.0 lua-5.2.4 lua-5.2.3 lua-5.2.2 lua-5.2.1 lua-5.2.0 lua-5.1.5 lua-5.1.4 lua-5.1.3 lua-5.1.2 lua-5.1.1 lua-5.1 lua-5.0.3 lua-...
Lua源码分析Lua源码分析Lua源码分析Lua源码分析Lua源码分析Lua源码分析Lua源码分析Lua源码分析
这个是lua的源码分析,lua的源码写的非常好,整个设计的结构非常巧妙,不管是对于学习lua本身还是c语言的数据结构都非常有帮助。
第一章概览由甮由源文件划分 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮
Lua 5.3.0源码,其中带VS2012的解决方案和项目文件。在压缩包中的win_build中包含了VS2012构建用的文件和目录,可以将Lua核心库编译成动态库或静态库,可以生成Lua编译器和命令行解释器。但是,Lua5.3.0的编译器luac...
Lua被设计成很容易和传统的C/C++整合的语言。这种语言的二元性带来了极大的好处。Lua是一个小巧而简单的语言,因为Lua不致力于做C语言已经...Lua所提供的机制是C不善于的:高级语言、动态结构、简洁、易于测试和调试等
lua源码,包含工程。
里面有风云 大神写的对lua 的源码剖析。还有lua5.2源码。
Lua 5.2.3源码,其中带VS2012的解决方案和项目文件。在压缩包中的win_build中包含了VS2012构建用的文件和目录,可以将Lua核心库编译成动态库或静态库,可以生成Lua编译器和命令行解释器。但是,Lua5.2.3的编译器luac...
Lua 源码赏析.pdf, 其中有着非常棒的lua源代码资源可供学习。下载文件为该书的百度云连接地址。
当然 Lua 5.0 我也读过,4.0 和 3.2 则读的不多。 最近有一点空闲,想续写我那本 Lua 源码欣赏。按我心里的计划,还有大约 6 章。虚拟机、字节码持久化、C API 、解释器、GC、库函数。 新添了一章关于虚拟机的,...
Lua CJSON 为 Lua 语言提供高性能的 JSON 解析器和编码器,其性能比纯 Lua 库要高 10 到 20 倍。Lua CJSON 完全支持 UTF-8 ,无需依赖其他非 Lua/LuaJIT 的相关包。
做了那么多 Lua 脚本破解,我们来尝试写一个不能被破解的加密。 所谓不能被破解,并不是真正不能被破解,只是在没有密码的情况下很难破解。
Lua 5.2.2源码,其中带VS2012的解决方案和项目文件。在压缩包中的win_build中包含了VS2012构建用的文件和目录,可以将Lua核心库编译成动态库或静态库,可以生成Lua编译器和命令行解释器。但是,Lua5.2.2的编译器luac...
Windows版:lua-utf8.dll(若是用在openresty中,openresty版本需使用32位版本,使用64位版本时会报错“lua-utf8.dll 不是有效的 Win32 应用程序”) 将lua-utf8库放在openresty安装目录下,使用时用require引入。
云风新作-----lua源码导读。目前网上最好的lua源代码阅读教程。帮助你快速理解lua实现原理。
Lua经典编程书籍, 编程指南.doc ,Lua程序设计_第二版_中文.dpf ,Programming in Lua, 2Nd Edition.pdf。 lua编程书籍,高清版,带目录,非常好的参考书
redis-lua 是 Redis 的 Lua 语言的客户端开发包。 示例代码: require 'redis' local redis = Redis.connect('127.0.0.1', 6379) local response = redis:ping() -- true redis:set('usr:nrk', 10) redis:set('usr...
云风写的Lua源码欣赏,基于lua5.2版本源代码解析,对于初初学习lua语言的有很不错的帮助
用sublime调试lua,lua中需要 require 'cjson',使用cjson.dll报错,可以将该cjson.lua直接放入同一目录下。