ad

《自己动手写 Python 虚拟机》_更理解虚拟机的意义_6.3 Native 函数

网友投稿 138 2023-11-07

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

6.3 Native 函数

在 Python 中有很多内建函数,例如 range 、xrange 和 len 等都是内建函数。本节 就通过实现 len 方法来讲解如何在虚拟机里实现 native 函数。

需要明确的第一件事情就是,native 函数也是一个普通对象,它本质上与 Func- tionObject并没有什么不同。所以仍然可以使用FunctionObject 来代表 native 函 数。不同的是,普通的 FunctionObject 的定义是通过字节码 MAKE_FUNCTION 来实现的,上一节重点介绍了这个机制。而 native 函数却没有对应的 Python 字节 码,它的所有实现都在虚拟机内部,也就是说,native 函数都是使用C+ 来实现的 此处需要一个手段把CALL_FUNCTION 与虚拟机内部的实现联系起来,还是要在 FunctionObject 身上打主意。

在 FunctionObject 里增加一个方法,名为 call 。当检查到当前的 FunctionOb- ject 是 native 函数时,就通过 call 方法去调用相关的逻辑。

《自己动手写 Python 虚拟机》_更理解虚拟机的意义_6.3 Native 函数

要完成以上功能,第一个要解决的问题,就是如何判断一个 FunctionObject 所 代表的是不是 native 函数。这个问题是容易解决的,就像之前使用Object 的 Klass tionKlass 来代表 native 函数,代码如代码清单6.19所示。

代码清单6.19 NativeFunctionKlass

//[runtime/functionObject.hpp]

class NativeFunctionKlass:public

private:

NativeFunctionKlass();

static NativeFunctionKlass

public:

static

};

//[runtime/functionObject.cpp]

NativeFunctionKlass*NativeFunctionKlass::instance =NULL;

NativeFunctionKlass*NativeFunctionKlass::get_instance()(

if(instance ==NULL)

instance =new NativeFunctionKlass();

return instance;

}

NativeFunctionKlass::NativeFunctionKlass()(

set_super(FunctionKlass::get_instance());

如果要创建一个 native 函数,只需要把它的 klass 指 向 NativeFunctionKlass 的

实例即可。

第二个要解决的问题,是如何实现 call 方法。思考一下 len 、range 等都是 native 函数,它们 call 方法的逻辑各不相同。 一种策略是像之前实现 print 方法一样,为每 一种不同的对象实现不同的 print 方法。这样做的话,就是为 len 这个函数对象创建 一个独立的 klass, 为 range 这个函数对象创建 一个独立的 klass, 在 klass 内部实现 不同的 call 的逻辑。当然可以这样做,但是太复杂了。回到问题的本源,len 和 range 都是 native 函数,所不同的只是它们被调用时要执行什么功能。其实可以使用函数 指针来完成这个需求,代码如下:

1 HiObject*len(ObjList args);

2 typedef HiObject*(*NativeFuncPointer)(ObjList args);

3

4 class FunctionObject:public HiObject(

5 private:

6

7 NativeFuncPointer _native_func;

8

public:

10 FunctionObject(NativeFuncPointer nfp);

11

12 HiObject * call(ObjList args);

13 };

在 FunctionObject 的定义里引入一个函数指针,这个指针指向的函数,可以接 受 ObjList 作为参数,并且返回值类型是 HiObject* 。 将所有的参数都放到参数列 表args 中去了,而args 是不定长的,所以理论上这种类型可以接受任意多的参数。 用于实现 native 函数是绰绰有余的。接下来,看一下上面的声明所对应的具体实 现,代码如下:

1 FunctionObject::FunctionObject(NativeFuncPointer nfp){

2 _func_code =NULL;

3 _func_name =NULL;

4 _flags =: 0;

5 _globals =NULL;

6 _native_func =nfp;

7

8 set_klass(NativeFunctionKlass;:get_instance());

9

10

11 HiObject*FunctionObject::call(ObjList args){

12 return(*_native_func)(args);

13

实现了 NativeFunctionKlass 以后,就可以在 FunctionObject 中使用它了,将 FunctionObject 的 klass 设为 NativeFunctionKlass 的实例,这个 FunctionObject 就 代表一个 native 函数。同时,要把函数指针指向具体的函数实现。在call 方法里,通 过指针调用具体的方法。在 len 的具体实现中,只需要调用对象的 len 方法即可,目 前虚拟机里只有String 类型,因此,在 StringKlass 中添加 len 的实现。

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

上一篇:跟着一起学《Excel VBA跟卢子一起学 早做完 不加班 基础入门版》_2.5 公有和私有的设置和作用
下一篇:《Python+3自动化软件发布系统》Django 2实战_了解Python的更好方法_5.1 用户管理简介
相关文章

 发表评论

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

×