美文网首页
基础: Lua函数闭包

基础: Lua函数闭包

作者: 码上述Andy | 来源:发表于2022-03-18 22:55 被阅读0次

函数是所有编程语言的执行单元或者说是行为,函数编译之后由一系列数据组成,比如指令集数组、常量数组、调试信息、本地变量、起始行信息等。lua也一样,函数闭包也是lua中执行单元,lua字节码执行过程中产生的数据结构。通过结构体定义可以看出由函数原型和upvalue数组组成,lua闭包=函数原型+upvalue。而函数原型为编译阶段生成的。分为CClosure和LClosure。
1).具体结构如下:

#define ClosureHeader \
    CommonHeader; lu_byte nupvalues; GCObject *gclist

typedef struct CClosure {
  ClosureHeader;
  lua_CFunction f;
  TValue upvalue[1];  /* list of upvalues */
} CClosure;

typedef struct LClosure {
  ClosureHeader;
  struct Proto *p;
  UpVal *upvals[1];  /* list of upvalues */
} LClosure;

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

2).闭包的生成过程:

closure.png

*lauxlib.h/lauxlib.c:luaL_dofile-->luaL_loadfile-->luaL_loadfilex-->lua_load(lapi.c)

*lapi.c:luaD_protectedparser

*ldo.c:luaD_protectedparser-->f_parser-->luaY_parser(文本)/luaU_undump(二进制)

lundump.c:

1.luaU_undump-->luaF_newLclosure:创建一个 closure, 压入栈顶

LClosure *luaF_newLclosure (lua_State *L, int nupvals) {
  GCObject *o = luaC_newobj(L, LUA_VLCL, sizeLclosure(nupvals));
  LClosure *c = gco2lcl(o);
  c->p = NULL;
  c->nupvalues = cast_byte(nupvals);
  while (nupvals--) c->upvals[nupvals] = NULL;
  return c;
}

2.loadFunction:加载Proto(函数原型)

static void loadFunction (LoadState *S, Proto *f, TString *psource) {
  f->source = loadStringN(S, f);
  if (f->source == NULL)  /* no source in dump? */
    f->source = psource;  /* reuse parent's source */
  f->linedefined = loadInt(S);
  f->lastlinedefined = loadInt(S);
  f->numparams = loadByte(S);
  f->is_vararg = loadByte(S);
  f->maxstacksize = loadByte(S);
  loadCode(S, f);
  loadConstants(S, f);
  loadUpvalues(S, f);
  loadProtos(S, f);
  loadDebug(S, f);
}

Proto函数原型,编译生成产物:

typedef struct Proto {
  CommonHeader;
  lu_byte numparams;  /* number of fixed (named) parameters */
  lu_byte is_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 sizeabslineinfo;  /* size of 'abslineinfo' */
  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 */
  Upvaldesc *upvalues;  /* upvalue information */
  ls_byte *lineinfo;  /* information about source lines (debug information) */
  AbsLineInfo *abslineinfo;  /* idem */
  LocVar *locvars;  /* information about local variables (debug information) */
  TString  *source;  /* used for debug information */
  GCObject *gclist;
} Proto;

小结:以上为函数闭包的几个核心数据部分。函数原型是编译生成的产物而函数闭包是脚本原型是构建出来的,由数据原型和upvalue组成,内部核心结构:Proto, CallInfo。

相关文章

  • 基础: Lua函数闭包

    函数是所有编程语言的执行单元或者说是行为,函数编译之后由一系列数据组成,比如指令集数组、常量数组、调试信息、本地变...

  • Lua语言学习教程

    lua闭包 函数尾调用 迭代器

  • Lua极简入门(七)——函数高级特性(闭包)

    闭包 当出现一个函数内嵌套另一个函数时,嵌套函数可以访问父函数的数据及资源,称为闭包。Lua的闭包原则就是一个函数...

  • lua闭包函数

    简单释义:函数里套函数,里层函数可以访问外层函数的所有局部 变量 1,lua中函数是第一类值 (他们可以存储在变量...

  • Lamda-闭包-匿名方法

    Lamda--Java 例子 闭包 常见在JavaScript,Lua可以实现变量往上级解析.本质匿名函数

  • lua基础

    fact阶乘 for循环 table 闭包 类 UnPack 这篇文章主要介绍了Lua UnPack函数用法实例,...

  • 闭包和函数

    闭包的基础概念: 闭包就是能够读取其他函数内部变量的函数 闭包的使用场景: 当需要记录一个函数的返回值的时候,...

  • Swift 基本语法(函数, 闭包)

    前言 接上篇, 这篇聊一下 Swift中的 函数, 闭包 一 函数 二 闭包 Swift 基础 先介绍三篇, ...

  • 前端面试题(持续补充)

    js,node.js基础: 闭包 闭包是能够读取其他函数内部变量的函数。在js中,只有函数内部的子函数可以访问内部...

  • Python 中的闭包

    外部函数返回内部函数简称闭包。闭包是装饰器的基础,装饰器就是用于改变原来函数状态,方法的函数。因为函数可接受的参数...

网友评论

      本文标题:基础: Lua函数闭包

      本文链接:https://www.haomeiwen.com/subject/kygwdrtx.html