ad

《自己动手写 Python 虚拟机》_更理解虚拟机的意义_3.2 加载 CodeObject

网友投稿 105 2023-11-07

【摘要】 本书摘自《自己动手写 Python 虚拟机》一书中第3章,第2节,海纳编著。

3.2 加载 CodeObject

《自己动手写 Python 虚拟机》_更理解虚拟机的意义_3.2 加载 CodeObject

经过上面的分析,大概了解了一个 pyc 文件的结构。现在就动手写一个 pyc 文 件的分析程序,在内存中重建 CodeObject, 然后尝试着去执行它。

读取文件内容

需要做的第一件事就是写程序打开pyc 文件,并将其内容逐字节读入。为了加 速文件的读操作,可以使用缓冲区。因此可以封装出一个专用于读文件的类,代码如 代码清单3.1所示。

编译并执行后,读出来的魔数与使用hexdump 工具查看的内容是相符的。我最 早使用 railgun 来命名工程,所以就一直延用了这个名字。读者完全可以给自己的虚 拟机起一个不同的名字,只需要在编译的时候,指定目标文件的名字即可,代码如下

3.2.1 准备工具

1. 列 表

接下来,要实现一个列表来表达 pyc 文件中的元组结构。为了节约内存,此处希 望这个列表是可以动态扩展的。这样的话,可以在一开始让列表的容量小一些,当元 素越来越多时,再重新分配内存。另外,列表作为一个容器,希望它能容纳各种类型 的元素,因此,这里使用模板来实现列表,如代码清单3.3所示。

在 ArrayList 类里定义了元素数组的大小_length, 指向元素数组的指针_array, 并 且使用_size 来指示当前列表里有多少个有效元素。然后又定义了add 方法,用于向列 表的末尾插入元素,insert 方法向指定的位置插入元素,get 方法用于获取指定位置的元 素 ,set 方法用于设置指定位置的元素。还有一个私有方法 expand, 当有效元素数量超 过元素数组容量的时候,可以扩展元素数组。具体实现的代码如清单3.4所示。

2. 字符

在 Python 中,所有的数据都是对象,字符串、整数和浮点数是对象,类定义、模 块和函数也是对象,它们都有共同的基类 object 。 因此在虚拟机中也引入了同样的 一个超类,定义为 HiObject 。 虚拟机中处理的所有数据都将会是一个 HiObject 的 实例。整数字符串也同样会是它的子类。

选择重新实现字符串类而不是借用C+ 的 string 类,是为了能与虚拟机中的其 他对象保持兼容。另外,重新实现保证了对内存使用的绝对控制权,这为将来实现自 动内存管理打下了基础。

一个字符串,最基本的属性就是它的长度和内容。内容可以用一个 char 类型的 指针指向字符串的开头。定义的字符串类代码如清单3.6所示。

注意, 一般来说,应坚持在头文件中只提供声明,方法的具体实现都放到 cpp 文 件中。这样做的好处是,在定义头文件的时候,不必额外再引入其他头文件,最大化 地避免了头文件的循环依赖。只有当函数体十分短小,例如 get 、set 方法,或者这个 类的使用范围极小的情况下,才会把实现放到头文件中去。

在这个思路的指导下,把 HiString 的构造放到 cpp 文件中,代码如清单3.7 所示。

HiString 的构造方法里有一点要注意,字符0在字符串里是一个合法的字符,所 以不能直接使用strcpy 来进行字符串的拷贝操作,因此这里使用了逐字节拷贝的笨 办法。当然这里也可以使用 memcpy, 读者可以自行添加。

由于头文件中往往都是类型声明,在后面的讲解中,如果不是特别必要,头文件 的内容就不再展示了,大家可以通过本书附带的源代码学习。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们 [email protected] 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:《Python+3自动化软件发布系统》Django 2实战_了解Python的更好方法_2.4.3 Django 框架的工作机制
下一篇:《Python学习笔记 从入门到实战》_更了解Python的途径之一_5.1.6 实现 switch 语句的功能
相关文章

 发表评论

暂时没有评论,来抢沙发吧~

×