您的位置:首页 > 理论基础 > 数据结构算法

Lua 数据结构--Closure

2017-03-28 20:48 148 查看
 在 lua 中函数是作为第一类值存在的,即它和表、字符串、数值一样可以被变量引用。函数有三种类型 lua 函数 (LUA_TLCL)、轻量级 C 函数 (LUA_TLCF)、C 函数 (LUA_TCCL)。其中 LUA_TLCL 和 LUA_TCCL 属于 GCUnion–需要被回收的类型,被称为 Closure。当
LUA_TCCL 不包含 upvalue 时,直接用 C 函数指针即可,不必构造 Closure 对象, 也就是 LUA_TLCF。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

/* lua.h */

/* Type for C functions registered with Lua */
typedef int (*lua_CFunction) (lua_State *L);

/* lobject.h */

/* Variant tags for functions */
#define LUA_TLCL  (LUA_TFUNCTION | (0 << 4))  /* Lua closure */
#define LUA_TLCF  (LUA_TFUNCTION | (1 << 4))  /* light C function */
#define LUA_TCCL  (LUA_TFUNCTION | (2 << 4))  /* C closure */

/* Closures */
typedef struct CClosure {
GCObject *next;
lu_byte tt;
lu_byte marked;
lu_byte nupvalues;  /* nums of upvalue */
GCObject *gclist;
lua_CFunction f;
TValue upvalue[1];  /* list of upvalues */
} CClosure;

typedef struct LClosure {
GCObject *next;
lu_byte tt;
lu_byte marked;
lu_byte nupvalues;  /* nums of upvalue */
GCObject *gclist;
struct Proto *p;
UpVal *upvals[1];   /* list of upvalues */
} LClosure;

typedef union Closure {
CClosure c;
LClosure l;
} Closure;

  lua 的闭包分成两类:CClosure 是 C 的函数闭包。LClosure 是 Lua 的函数闭包。


LClosure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
3839
40
41
42
43
44
45

/* lobject.h */

/* Function Prototypes */
typedef struct Proto
{
GCObject *next;
lu_byte tt;
lu_byte marked;
lu_byte numparams;    /* number of fixed parameters */
lu_byte is_vararg;    /* 2: declared vararg; 1: uses vararg */
lu_byte maxstacksize; /* number of registers needed by this function */
int sizeupvalues;     /* size of 'upvalues' */
int sizek;            /* size of 'k' */
int sizecode;
int sizelineinfo;
int sizep;            /* size of 'p' */
int sizelocvars;
int linedefined;      /* debug information  */
int lastlinedefined;  /* debug information  */
TValue *k;            /* constants used by the function */
Instruction *code;    /* opcodes */
struct Proto **p;     /* functions defined inside the function */
int *lineinfo;        /* map from opcodes to source lines (debug information) */
LocVar *locvars;      /* information about local variables (debug information) */
Upvaldesc *upvalues;  /* upvalue information */
struct LClosure *cache;  /* last-created closure with this prototype */
TString  *source;     /* used for debug information */
GCObject *gclist;
} Proto;

/* lfunc.h */

/* Upvalues for Lua closures */
struct UpVal
{
TValue *v;        /* points to stack or to its own value */
lu_mem refcount;  /* reference counter */
union {
struct {        /* (when open) */
UpVal *next;  /* linked list */
int touched;  /* mark to avoid cycles with dead threads */
} open;
TValue value;   /* (when closed) the value */
} u;
};

  LClosure 由 Proto 和 UpVal 组成。Proto 描述了 lua 函数的函数原型,记录了函数原型的字节码、函数引用的常量表、调试信息、参数、栈大小等信息。UpVal 保存了对 upvalue 的引用。它直接用一个 TValue 指针引用一个 upvalue 值变量。当被引用的变量还在数据栈上时,这个指针直接指向栈上的 TValue,那么这个 upvalue 被称为开放的。由于 lua 的数据栈的大小可扩展,当数据栈内存延展时 (realloc),其内存地址会发生变化,这时需要将 upvalue
拷贝到 UpVal.u.value 中保存。


CClosure

  CClosure 由 lua_CFunction 和 TValue 组成。C 函数可以用闭包的方式嵌入 lua,与 LClosure 相比 CClosure 天生就是关闭的。因此,直接使用 TValue 来保存 upvalue。而 lua 与 C 交互的函数原型统一使用 lua_CFunction。当某个函数没有 upvalue 时,则不需要创建闭包直接使用 lua_CFunction。也称为 light C function。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: