版本整理日期: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.2lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));return 1;
}
/*1.1lauxlib.c调用lua_tonumber,并且对参数进行一个检测,可以看成是一个辅助性的函数
*/
LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {//lua_tonumber见1.1.1lua_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.1lapi.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;}elsereturn 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.2lapi.clua_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的文件结构和思考方式相关推荐

  1. Lua源码分析 - 基础篇 - Lua源码的结构和架构图(01)

    目录 一.Lua语言简介 二.Lua架构图 三.Lua源码结构 很久很久没有写博客了,一直忙于工作和项目,最近依然想静下来阅读一些好的源码.自从读完了Nginx和Memcache的源码后,对服务器端的 ...

  2. Lua源码分析 - 虚拟机篇 - 语义解析之Opcode执行(18)

    目录 一.虚拟机篇 - 指令执行状态机luaV_execute 二.虚拟机篇 - 状态机的具体实现原理 一.虚拟机篇 - 指令执行状态机luaV_execute 在<Lua源码分析 - 主流程篇 ...

  3. 【Android 事件分发】ItemTouchHelper 源码分析 ( OnItemTouchListener 事件监听器源码分析 二 )

    Android 事件分发 系列文章目录 [Android 事件分发]事件分发源码分析 ( 驱动层通过中断传递事件 | WindowManagerService 向 View 层传递事件 ) [Andr ...

  4. SpringBoot源码分析(二)之自动装配demo

    SpringBoot源码分析(二)之自动装配demo 文章目录 SpringBoot源码分析(二)之自动装配demo 前言 一.创建RedissonTemplate的Maven服务 二.创建测试服务 ...

  5. gSOAP 源码分析(二)

    gSOAP 源码分析(二) 2012-5-24 flyfish 一 gSOAP XML介绍 Xml的全称是EXtensible Markup Language.可扩展标记语言.仅仅是一个纯文本.适合用 ...

  6. Android Q 10.1 KeyMaster源码分析(二) - 各家方案的实现

    写在之前 这两篇文章是我2021年3月初看KeyMaster的笔记,本来打算等分析完KeyMaster和KeyStore以后再一起做成一系列贴出来,后来KeyStore的分析中断了,这一系列的文章就变 ...

  7. 【投屏】Scrcpy源码分析二(Client篇-连接阶段)

    Scrcpy源码分析系列 [投屏]Scrcpy源码分析一(编译篇) [投屏]Scrcpy源码分析二(Client篇-连接阶段) [投屏]Scrcpy源码分析三(Client篇-投屏阶段) [投屏]Sc ...

  8. Nouveau源码分析(二):Nouveau结构体的基本框架

    Nouveau源码分析(二) 在讨论Nouveau对Nvidia设备的初始化前,我准备先说一下Nouveau结构体的基本框架 Nouveau的很多结构体都可以看作是C++中的类,之间有很多相似的东西, ...

  9. ENS最新合约源码分析二

    ENS(以太坊域名服务)智能合约源码分析二 0.简介 ​ 本次分享直接使用线上实际注册流程来分析最新注册以太坊域名的相关代码.本次主要分析最新的关于普通域名注册合约和普通域名迁移合约,短域名竞拍合约不 ...

最新文章

  1. 方法对象java final关键字的用法
  2. python枪战项目计划书_燕山大学操作系统课程设计计划书
  3. 陈鑫136201010502
  4. iOS Cookie相关操作
  5. 图片碎片化mask动画
  6. 一元多项式的相加(单链表的应用)
  7. 设计师必收藏!!!让你灵感迸发的配色网站
  8. 只听几句话,百度AI就能模仿你的声音 | 附论文
  9. 你必须掌握的Python数据分析工具之Numpy
  10. 简单几何(四边形形状) UVA 11800 Determine the Shape
  11. 宽屏系统上播放幻灯片的设想
  12. JTAG与SWD接口定义
  13. Visual Studio Ultimate 2012 激活密钥
  14. 为什么现在社交电商这么火?
  15. JNCIS-SP学习指南卷1 第一章:协议无关的路由
  16. Lab: Username enumeration via different responses:通过不同的响应来验证用户名是否正确复盘
  17. iOS 应用唤起淘宝到指定商店页面
  18. 德国汉诺威地面材料展览会搭建就找上海宽创国际
  19. 将你的笔记本变成无线路由器
  20. echarts tooltip提示框 自定义小圆点(颜色、形状和大小等等)

热门文章

  1. Python网络爬虫,pyautogui与pytesseract抓取新浪微博数据,OCR
  2. 从文件加密到到视频文件进度条播放揭秘
  3. AI人工智能时代真的到来了吗?
  4. 人工智能从1.0时代到4.0时代
  5. 学习3D游戏建模的主要工具与技巧!
  6. GAN网络系列博客(三):不受坐标限制的GAN(StyleGAN3)
  7. 2018年中国捐赠百杰榜发布
  8. cvx matlab 求不出解可尝试方法 Failed Infeasible Unbounded
  9. matlab 有源电力滤波器,基于MATLAB的有源电力滤波器研究
  10. OpenCV的Rect 常用函数