Lua5.1.4代码分析(十七)-可变参数函数的实现

可变函数参数的实现相对简单。

首先来看看Lua中可变参数函数的使用方式。如果函数传入的参数是”…”,则表示这里的参数是可变参数,在使用时,它们最终会存储到一个名为arg的数组中。

如前面对函数的解析里面提到,在对一个函数的参数进行解析时,会走到parlist函数中,这里处理了变参参数的情况:

static void parlist (LexState *ls) {
  /* parlist -> [ param { `,' param } ] */
  FuncState *fs = ls->fs;
  Proto *f = fs->f;
 

Lua5.1.4代码分析(十六)-函数与Upvalue

Lua中的所谓upvalue是一类比较特殊的值,可以理解为在某函数内引用外部的数据。所以这里就涉及到垃圾回收相关的话题,比如函数A使用它的upvalue a,那么就需要保证a在函数A调用之前不会被Lua gc自动回收。里面还有一些其他细节。下面一一道来。

在前面提到的

如何在不同Lua虚拟机中传递函数

有一个需求,需要在同一个进程中不同的Lua虚拟机之间传递函数对象并且调用。

考虑了很久没啥进展。原来想干脆hack Lua的指针,因为是在同一个进程中的Lua虚拟机,所以看看能不能得到函数的内存。但是这次经历让我发现其实Lua封装的非常好,在gdb中根本看到Lua State这个结构体具体的内容,也只能按照它提供的API做它允许的操作,再次让我对Lua的实现敬仰程度增加了不少。

后来去Lua maillist发问,已经有老外实现了类似的项目

Lua5.1.4代码分析(十五)-Lua继承机制分析

Lua并不是一门以OO为卖点的脚本语言,但是这并不妨碍在Lua中使用Lua的一些特性来实现类面向对象的特性。

先简单看看Lua中实现继承的简单示例代码,再展开分析。如下定义了两个模块,base.lua和test.lua,其中后者继承自前者:
base.lua

module( "base", package.seeall )
function new( )
    local obj = {}
    setmetatable( obj, { __index = base } )
    return obj
end

test.lua

module( "test", package.seeall )
setmetatable( test,

Lua5.1.4代码分析(十四)-Lua外部模块加载机制

前面已经提到了Lua的内部模块加载机制,今天谈谈如何加载外部模块.与模块加载相关的库都在package库中提供,代码实现在loadlib.c中.

先来看Lua中与模块相关的几个函数.

1)module
在定义一个Lua模块时,第一句代码一般都是module(xxx).来看这一句背后的含义.module调用对应的c函数是loadlib.c中的函数ll_module:

static int ll_module (lua_State *L) {
  const char *modname = luaL_checkstring(L, 1);
  int loaded = lua_gettop(L) + 1;  /* index of _LOADED table */
 

Lua5.1.4代码分析(十二)-Lua内部模块的注册

今天讲解Lua内模块的注册机制.其实Lua自带的模块并不多,这是Lua被诟病比较多的地方,这样的坏处是很多东西需要自己造轮子没有标准的实现(虽然可以实现为库也不那么不方便使用),好处就是Lua足够的小,毕竟它的设计目标是定位成一个嵌入式的轻量级语言的.

这部分需要的知识点不多,但是可以顺带着理解Lua中的一些概念.

但是在讲解之前,还是先来看看另一个貌似并不那么相关的函数index2adr

static TValue *index2adr

Lua5.1.4代码分析(十一)-函数的调用

上一篇中,已经提到了函数的信息是如何在lua中保存的,本篇继续来讲解函数的调用机制.

首先谈谈函数的参数是如何处理的.
在分析函数的定义时,首先调用parlist处理函数的参数.简单起见,这里考虑函数的参数是确定的情况:

static void parlist (LexState *ls) {
  /* parlist -> [ param { `,' param } ] */
  FuncState *fs = ls->fs;
  Proto *f = fs->f;
  int nparams = 0;
  f->is_vararg = 0;
  if (ls->t.token != ')') {  /* is `parlist' not empty? */
    do {
      switch (ls->t.token)

十字链表的AOI算法

看了云风写的

Lua5.1.4代码分析(十)-函数的定义

Lua源码中,专门有一个结构体FuncState用来保存函数相关的信息.其实,即使没有创建任何函数,对于Lua而言也有一个最外层的FuncState数据.来看看这个结构体的定义:

typedef struct FuncState {
  Proto *f;  /* current function header */
  Table *h;  /* table to find (and reuse) elements in  */
  struct FuncState *prev;  /* enclosing function */
  struct LexState *ls;  /* lexical state */
  struct lua_State *L;  /* copy of the Lua state */
  struct BlockCnt *bl;  /* chain of current blocks */
  int pc;  /* next

Lua5.1.4代码分析(九)-循环类操作

有了前面的基础,再来看循环类指令就很简单了,因为循环类指令,本质上可以改写成逻辑跳转类指令.

就以最简单的for循环来讲解循环类指令的实现.Lua中的for循环有两种形式,一种是平时常见的数字循环类,另一种是遍历数组,Hash的for循环语句.当然还是第一种更简单,所以就以数字循环类指令来讲解.

与数字for循环类指令相关的Opcode有两个:

OP_FORPREP,/*	A sBx	R(A)-=R(A+2); pc+=sBx				*/

OP_FORLOOP,/*	A sBx	R(A)+=R(A+2);
			if R(A) less than

Pages: Prev 1 2 3 4 5 6 7 8 9 Next