Excel 名称框概述-英雄云拓展知识分享
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 方法去调用相关的逻辑。
要完成以上功能,第一个要解决的问题,就是如何判断一个 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小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~