Lua 数据结构--Closure

 在 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
38
39
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。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用链表或者数组来实现集合的并操作。具体实现方法可以参考以下代码: ```c #include <stdio.h> #include <stdlib.h> #define MAXSIZE 100 typedef struct { int data[MAXSIZE]; int length; } Set; void initSet(Set *s) { s->length = 0; } void addElement(Set *s, int e) { if (s->length >= MAXSIZE) { printf("Set is full!\n"); return; } for (int i = 0; i < s->length; i++) { if (s->data[i] == e) { return; } } s->data[s->length++] = e; } void unionSet(Set *s1, Set s2) { for (int i = 0; i < s2.length; i++) { addElement(s1, s2.data[i]); } } void printSet(Set s) { printf("{"); for (int i = 0; i < s.length; i++) { printf("%d", s.data[i]); if (i < s.length - 1) { printf(", "); } } printf("}\n"); } int main() { Set A, B; initSet(&A); initSet(&B); addElement(&A, 1); addElement(&A, 2); addElement(&A, 3); addElement(&B, 2); addElement(&B, 3); addElement(&B, 4); unionSet(&A, B); printSet(A); return 0; } ``` 输出结果为:{1, 2, 3, 4}。 关于 Lua closure factory 的完整代码,可以参考以下示例: ```lua function makeCounter() local count = 0 return function() count = count + 1 return count end end c1 = makeCounter() print(c1()) -- 1 print(c1()) -- 2 c2 = makeCounter() print(c2()) -- 1 print(c1()) -- 3 ``` 这段代码实现了一个计数器,每次调用返回一个递增的数字。makeCounter 函数返回一个闭包,其中 count 变量被封装在闭包内部,不会被外部访问到。 关于中文加密,可以使用一些常见的加密算法,比如 AES、DES、RSA 等。具体实现方法可以参考相关的加密库或者算法实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值