让我们自定义反射系统

30 篇文章 2 订阅
9 篇文章 5 订阅

上周我们在DX12课程中讲解了如何定制反射系统,本篇是作为一个系统复习和总结,如果您已经参与上周直播,本篇可以帮助您总结这方面的系统框架。

实际上蓝图的反射系统和编译系统这些知识并不是非常新鲜的,早在接Java和各类脚本语言的时候就有大量运用。

为什么要用反射,它到底要干嘛?

实际上它的作用很重要,比如我们想接Lua脚本,java,js,php等,这个时候就需要这项技术,它可以帮我们快速建立C++和他们之间的通信,也就是C++调用脚本,脚本也可以反向调用C++。

那如何实现这种技术呢?

先探讨一下UE的反射。

如果大家有使用UE的经验就可以了解,我们在使用UE的时候是不是通过给对象头部增加标签的方式。比如变量标签,函数头上加个标签,类,结构体,枚举等,来作为反射的标记,这些反射标签还里面可以写很多元数据来表达反射的性质,比如你的函数类型是什么类型,纯函数还是一般函数还是事件,函数分类,可见性,编辑器显示方式等等?

我们标记玩标签后接下来就需要代码生成代码,这个就是我们所说的胶水代码,它是链接脚本和C++的关键。如果我们希望自己手写来实现C++和脚本,那么也没有问题。但是这些代码往往是重复的,没有必要的,我们不能写一个类就搞一堆胶水代码,实现函数反射,变量的反射,类的反射,结构体,枚举等。

什么不交给机器来帮我们生成这些代码呢?

我们采用的方式是代码扫描,这类方法也是最常用的,UE的反射构建工具也是采用了这种方法。

扫描我们主要是干什么事情呢?

1.第一阶段 代码收集:我们需要知道你的代码里面哪些需要反射,如何反射,这些需要一行行扫描,分析你的代码类,变量,类的类型,变量的类型,函数的类型等等

2.第二阶段 代码生成 :这个阶段基本上会将上文中代码收集的内容定向生成胶水代码,这些代码联系着脚本和C++.

接下来就是如何沟通的设计,首先我们需要这几样东西:

1.统一的字节码函数;

2.字节码表

3.结构解析器

什么是字节码函数?

我们需要定制一个统一的标准来实现函数的入栈和出栈包括它的参数入栈和出栈,我们这里采用的方法是函数指针,这个函数指针拥有一个统一的基础参数

1.本地对象:作为可以访问成员变量和函数使用。

2.结构解析器:作为读取字节码使用,后面会讲解。

3.引用返回:如果脚本拥有返回值,那么这个就是用来收集返回值。

这是一个标准,每走一个字节码我们都要去字节码表查询这个函数,并且执行里面的内容:

接下来我们探讨字节码表,这个字节码表很重要,它可以帮助我们快速解析脚本语言序列化后的字节,一层层解析,比如我们解析到第一个字节,我们需要知道第一个字节对应的字节码表是什么函数,通过函数再解析后面的数据,如此往复,就把数据解析完毕。

实际上没有我讲解的这么简单。

我们就拿一个函数为例:

我们先调用这个函数,再调用这个函数的时候我们需要为它构建一组参数,这些就是函数的参数。

然后我们才调用函数,把参数传入进入,这个就是一个简单的调用。

既然我们有字节码表和函数统一的指针,那么就剩下解析器。

这个解析器到底是干嘛的?

它可以帮忙一层层解析字节码,解析到我们想要的内容。

对于解析我们需要定义一个通用的标准,比如我们要解析函数,需要先存储这个函数对于的参数,然后根据字节码表来寻找这个函数对应的字节码函数,每递进一个字节码,我们都会再字节码表查找,发现这个是int解析,那么我们会按照字节码向后偏移4个字节来作为int的大小,接着继续解析,第二个是float.我们再调用float的解析器,向偏移4个字节。如何我们发现的是string,那么我们后寻找字符串的/0,有/0我们会自动结束切割字节码。

这个就是解析器的作用,至此我们的蓝图的反射和解析就完成了。

实际上这块内容已经在编辑器开发进阶 的第五和第六章详细的探讨过,并且已经实现平行于蓝图的虚拟机技术。有需求和兴趣可以看看。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值