`

LUA源码分析五:元表

    博客分类:
  • LUA
阅读更多

 

版本整理日期:2011/4/21

 

元表其实就是可以让你HOOK掉一些操作的一张表。

表的定义在ltm.h/c的文件里。对元表的调用在lvm文件里。

来看看是怎么hook的。首先定义了一堆的枚举

 

typedef enum {
  TM_INDEX,
  TM_NEWINDEX,
  TM_GC,
  TM_MODE,
  TM_EQ,  /* last tag method with `fast' access */
  TM_ADD,
  TM_SUB,
  TM_MUL,
  TM_DIV,
  TM_MOD,
  TM_POW,
  TM_UNM,
  TM_LEN,
  TM_LT,
  TM_LE,
  TM_CONCAT,
  TM_CALL,
  TM_N		/* number of elements in the enum */
}

 

 

除了TM_INDEXTM_NEWINDEX外,其他的都是实现定义好的操作符。也就是说如果你要改变s1+s2这样的行为,只要直接设置TM_ADD的函数即可。TM_INDEXTM_NEWINDEX表示读取和等于。比如s[s’]=x[‘x’’]中,左边的[s’]如果没有这个字段则从TM_NEWINDEX中读取,右边的同理。

元表可以存在于这些对象上:

 

 

const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
  Table *mt;
  switch (ttype(o)) {
    case LUA_TTABLE:         //表
      mt = hvalue(o)->metatable;
      break;
    case LUA_TUSERDATA:      //自定义对象
      mt = uvalue(o)->metatable;
      break;
    default:                 //全局
      mt = G(L)->mt[ttype(o)];
  }
  return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
}

 

 

lua源码里,对元表的访问其实也是很简单的:

我们直接从虚拟机代码开始跟起,通过元表存在的对象类型上,会从OP_GETTABLE上跳转,代码如下

 

case OP_GETTABLE: {
        Protect(luaV_gettable(L, RB(i), RKC(i), ra));
        continue;
      }

 

 

luaV_gettable中,会先扫描是否有RKC(i)的值。即上文提到的s[s’]=x[‘x’’]中的[s’]。如果有则返回,直接读取;否则扫描TM_INDEX字段,然后判断里面是否函数,如果是则进入调用。代码如下:

 

 

void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
  int loop;
  for (loop = 0; loop < MAXTAGLOOP; loop++) {
    const TValue *tm;
    if (ttistable(t)) {  /* `t' is a table? */
      Table *h = hvalue(t);
      const TValue *res = luaH_get(h, key); /* do a primitive get */
      if (!ttisnil(res) ||  /* result is no nil? */
          (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
        setobj2s(L, val, res);
        return;
      }
      /* else will try the tag method */
    }
    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
      luaG_typeerror(L, t, "index");
if (ttisfunction(tm)) {
  //这里是我们的跳转点
      callTMres(L, val, tm, t, key);
      return;
    }
    t = tm;  /* else repeat with `tm' */ 
  }
  luaG_runerror(L, "loop in gettable");
}

 callTMres(L, val, tm, t, key);往下跟,先把要调用的函数(tm)压入,接着是lua固用的调用代码流程(如果你熟悉前篇的话),最后又来到虚拟机的OP_CALL处,代码如下。

 

     case OP_CALL: {
        int b = GETARG_B(i);
        int nresults = GETARG_C(i) - 1;
        if (b != 0) L->top = ra+b;  /* else previous instruction set top */
        L->savedpc = pc;
      //这里是我们的进入点
        switch (luaD_precall(L, ra, nresults)) {

 

 

在熟悉的luaD_precall,来到我们设定的C++函数处。代码如下:

 

int luaD_precall (lua_State *L, StkId func, int nresults) {
    n = (*curr_func(L)->c.f)(L);  /* do the actual call */
}

 元表虽然给我们提供了一种hook的手法,但是一切还是以实际需求来进行选择运用。不一定一切非要元表的思维来实现

 

 

1
3
分享到:
评论

相关推荐

    lua源码分析

    Lua源码分析关注的是其内部实现机制,这些机制包括了以下几个主要方面: 1. 全局状态机和内存管理:Lua使用一种全局状态机来管理程序的状态,包括变量、函数、模块等。内存管理是任何编程语言实现中的关键部分,Lua...

    Lua源码分析

    以下是对Lua源码分析的一些详细知识点。 Lua源码主要可以分为几个部分:虚拟机运转的核心功能、源文件划分、代码风格、Lua核心、代码翻译及预编译字节码、内嵌库、独立解析器及字节码编译器、阅读源代码的次序。...

    云风-lua源码欣赏-lua-5.21

    《云风-lua源码欣赏-lua-5.21》通过各个章节的深入分析和讲解,为读者提供了一个全面了解Lua内部机制的平台。无论是对Lua语言的底层原理感兴趣,还是希望提高Lua编程技巧,亦或是有志于进行Lua相关技术的扩展开发,...

    lua 源码剖析

    6. **元方法和元表**:lua的元表机制使得对象可以拥有自定义的行为,是实现面向对象编程的关键。源码中元表的相关实现主要在`lobject.c`和`ltm.c`。 7. **C API**:lua的C API允许C/C++代码与lua交互,包括创建和...

    lua源码鉴赏云风

    6. **函数和表的实现**:Lua中的函数和表是其强大之处,云风将深入解析它们的实现,包括闭包、元表、弱引用等特性。 7. **C API接口**:Lua提供了丰富的C API,允许C/C++代码与Lua交互。这部分内容会解释如何使用C ...

    lua脚本源码包

    通过分析lua_test的源码,你可以了解到如何在实际项目中嵌入lua,这对于嵌入式系统开发者来说是非常有价值的。你可以学习到如何在有限的资源环境下利用lua的灵活性和高效性,来增强软件的功能和可维护性。同时,lua_...

    lua 源码分析

    《深入剖析:Lua源码分析》 一、引言与背景 Lua,作为一种小巧而强大的脚本语言,凭借其高效性、灵活性以及易嵌入特性,在游戏开发、系统管理、Web应用等多个领域得到了广泛的应用。它由标准C语言编写而成,这不仅...

    Lua源码欣赏中文版

    首先,Lua源码的下载、阅读和分析需要一定的C语言基础,因为Lua是基于C语言实现的。官方提供的Lua5.0版本源码的中文解读文档可以作为理解源码的辅助材料。在开始阅读源码之前,应先了解Lua语言的标准和官方实现的...

    lua源码下载 Lua-5.3.4 源码 最新 截止2017-3-7

    通过分析和编译源码,你可以了解到Lua是如何高效地实现动态语言特性的,如闭包、元表、弱引用等。同时,也可以根据需求修改源码,创建定制版的Lua解释器,满足特定应用场景的需求。总之,研究Lua源码是提升编程技能...

    《Lua 源码欣赏》

    综上所述,这篇文章不仅对Lua源码进行了深入的分析,而且对Lua语言的设计理念和优化技巧进行了全面的讲解。对于希望深入了解脚本语言实现机制的程序员来说,这篇文章是一份宝贵的资料。通过对Lua源码的解读,我们...

    Lua中文教程+源码赏析

    这个资源包包含了“Lua中文教程”和“Lua源码赏析”两部分,旨在帮助初学者在短短两小时内快速掌握Lua编程基础,并通过源码分析深入理解其内部机制。 “Lua中文教程”可能涵盖以下内容: 1. **基础语法**:Lua的...

    Lua 源码剖析.rar

    7. **源码分析**:云风大神通过对Lua源代码的逐行解析,揭示了其内部工作原理。读者将了解到Lua的解释器如何解析和执行代码,以及虚拟机如何执行字节码。 8. **实例解析**:书中包含大量实例,帮助读者理解和应用所...

    lua源码导读---云风

    ### lua源码导读---云风 #### 概览 **Lua** 是一门轻量级、高效能的脚本语言,广泛应用于游戏开发、系统管理工具、网络应用等多个领域。本书《lua源码导读》旨在深入剖析 Lua 的源代码,帮助读者理解其内部实现...

    lua 源码,包含工程文件

    以上只是Lua源码中涉及的一部分知识点,实际的源码分析将更为深入,涵盖虚拟机实现、错误处理、字符串操作、线程模型等多个方面。对于想要深入理解和定制Lua的开发者来说,这将是一份宝贵的资源。

    云风《Lua源码欣赏》1积分

    《Lua源码欣赏》是一本由云风编写的书籍,旨在对Lua 5.2版本的源代码进行解析,为初学者提供了解Lua语言内部工作原理的途径。本书通过分解各个章节内容,使得读者能够以独立的形式学习和理解Lua的各个组成部分。 ...

    lua分析分析

    总结来说,Lua源码的分析不仅有助于我们掌握其核心机制,还能够提升我们的编程能力,使我们能够更深入地利用Lua来解决实际问题。无论你是游戏开发者、系统管理员,还是对编程语言感兴趣的爱好者,理解Lua的源码都将...

    lua-5.3.4源码

    4. 元表与元方法:通过元表实现面向对象编程,元方法用于操作表的行为。 二、虚拟机与字节码 1. Lua虚拟机(VM):Lua的执行引擎,负责解释执行字节码。在5.3.4版本中,VM进一步优化,提升了执行效率。 2. 字节码:...

    lua 源码鉴赏 高清

    10. **元表与元方法**:Lua 的元表机制使得用户可以通过元表自定义对象的行为,如重载算术运算符、比较操作等。元方法是通过元表调用的特殊方法。 通过阅读《Lua 源码鉴赏》高清文档,你可以深入了解 Lua 的实现...

    打地鼠lua源码

    6. **面向对象编程**:虽然lua不是纯面向对象的语言,但通过table和元表,可以实现类的模拟。源码可能包含对地鼠类和游戏类的定义,实现面向对象的设计模式。 7. **错误处理**:lua的error和pcall函数可用于处理...

    Lua源码欣赏2012年11月-云风.pdf

    “Table的实现”章节会聚焦于Lua中表(table)这种核心数据结构,包括它是如何支持关联数组、序列以及元表(metatable)等特性的。在“全局状态机及内存管理”章节中,文档将讨论Lua中的内存分配、垃圾收集机制以及...

Global site tag (gtag.js) - Google Analytics