前言
- 文章之后会修改.
最近一些文章互相关联性较高, 可能随着某篇文章某些内容的深扒, 而导致一些内容更连贯, 并对所有相关内容进行修改 - 源码版本4.22
大钊:《InsideUE4》UObject(六)类型系统代码生成重构-UE4CodeGen_Private
在前面的文章中,我们对一个空UObject类进行了一系列的分析, 那么如果不是空类呢?
这就是这篇文章的内容了,内容较多且繁杂, 如果前面掌握不太好,那就回去复习!
同时内容较多, 受限于篇幅, 可能会省略掉很多对比等实际操作.
请根据步骤一步一步跟做, 不保证教会, 但保证看懂。
属性篇 第一节
添加一个float的成员变量, 重新生成项目, 然后与空类(UGAObject01)generated.h和generated.cpp进行对比。
// 后文简称与头文件(generated.h)或者实现文件(generated.cpp)
没有发现任何显著变化, 可以认为无变化。
属性篇 第二节
添加U宏标记, 与空类对比, 进行同样的步骤。
与头文件对比, 无明显变化
与实现文件相比, Z_Construct_UClass_UGAObject05_Statics这个反射信息结构体发生很大的变化
- NewProp_TestFloatValue_MetaData
名称直译, 新的属性_属性名称_元数据
这里是收集属性对应的元数据
- NewProp_TestFloatValue
从数据上看, 可以轻易的出, 这是这个属性对应的反射信息
跳一下结构体, 可以看到是FGenericPropertyParam这个结构体
属性值一一对应
这里只分析部分, 一些内容等用到的时候再分析.
NameUTF8 : 属性名称
PropertyFlags : 这个属性(EPropertyFlags)0x0010000000000000, 值实际是CPF_NativeAccessSpecifierPublic
Flags : 这个属性标记类属性的类别, 是个枚举, 这里是float
总共有下列这么多情况, 也就是说下面这些是所有可以加U宏的属性类型
- PropPointers
可以看到是一个FPropertyParamsBase指针数组, 存储多个反射参数信息的指针
参考注释内容, FPropertyParamsBase只是规定了常见初始序列, 及前几个内容是这几个属性, 其他的多多少少, 会根据不同情况, 做一些拓展.
FPropertyParamsBaseWithOffset在FPropertyParamsBase的基础上多了属性偏移一个int32值
FGenericPropertyParams又在FPropertyParamsBaseWithOffset的基础上多了元数据信息
所以, 存储一个最基础信息的数据, 根据EPropertyGenFlags获得实际的类型, 就能生成对应的变量信息
上述内容就可以得到属性的反射信息, 那么怎么管理到Class上面呢?
如上, 传入Class反射参数一个属性反射信息数组和相应数量
至此, 这个float值, 反射信息就被记录并可以合理生成了.
属性篇 第三节
我们进一步添加一些信息, BlueprintReadOnly, EditAnywhere, Catergory = "Test"
再和刚才的UGAObject05进行对比
元数据添加了一个Category
PropertyFlags值发生了变化
拆分可得, 多了CPF_BlueprintReadOnly | CPF_BlueprintVisible | CPF_Edit
属性篇 第四节
再加上一个Replicated标记呢?
头文件会添加GetLifetimeReplicatedProps的override声明
// 这也是那个常见错误, 标记属性同步之后, 编译报错, GetLifetimeReplicatedProps函数没有定义的原因
PropertyFlags值发生了变化, 多了CPF_Net
属性篇 第五节
修改同步方式为ReplicatedUsing, 与UGAObject07进行对比
可以看到此处RepNotifyFuncUTF8不在为空,为对应的函数名称
PropertyFlags值发生了变化, 多了CPF_RepNotify
那些UFunction相关的就之后再说了
属性篇 第六节
前文分析的都是单一float, 下文会开始分析一些数据类型
与float类型, 只是换了一下类型
等等, 可以看出这些基本都是相同的.
属性篇 第七节
bool值的实现与float, int相比有些特殊, 感觉是因为内存对齐的问题导致的
求大佬指导
属性篇 第八节
对比可以看到, FString,FName, FText实现和float, int类似
属性篇 第九节
看一下AActor的呢, 发现多了一个指针, 联系前文, 是不是很熟悉?
是一个构造AActor对应UClass的一个函数, 详情见之后的COD
以及PropertyFlags值发生了变化, 多了CPF_UObjectWrapper
可以看到, WeakObject和SoftObject的基本类似.
属性篇 第十节
TSubclassOf<>相比AActor属性相关多了一个Z_Construct_UClass_UClass函数指针, 预计是这里依赖到了UClass, 所以要获得其构造函数, 提前调用
TSoftClassPtr<>相比又不一样
统一比较一下
- struct FObjectPropertyParams
UClass* (*ClassFunc)(); - struct FClassPropertyParams
UClass* (*MetaClassFunc)();
UClass* (*ClassFunc)(); - struct FSoftClassPropertyParams
UClass* (*MetaClassFunc)();
具体区别在哪里? 可能在之后会有分析吧.
属性篇 第十一节
忽略调枚举本身的反射, 之后分析
枚举的处理就有些看不懂了, 相比前面属性的处理, 枚举这里有两个结构体信息
这是正常的反射信息, 函数指针是枚举对应对枚举UEnum的构建函数
这个,,, 由于ArrayDim两者相同, 所以可以对应到一起, 但用处,,, 看不懂.
属性篇 第十二节
忽略掉结构体本身的反射
相比来看, 也比较简单, 存了一个函数指针, 构建依赖的结构体(UScrUScriptStruct)
属性篇 第十三节
TArray这里的实现, 也是两个结构体, 一个是数组本身, 一个是数组对应的类型
数组对应类型结构体NewProp_TestValue_Inner数据很多都是空值, 只是为了收集数据类型.
TSet同TArray
TMap则类似, 有三个结构体, 一个键的数据类型,一个值的数据类型
其他同上
不过可以看到Offset这个值, 键为0, 值为1, 有做一定的区别
具体原因, 不知, 后文遇到分析.
属性篇 第十四节
PropertyFlags值发生了变化, 多了CPF_InstancedReference
并多了一个Z_Construct_UDelegateFunction_UGAObject26_TestGADelegate__DelegateSignature函数指针, 从代码上看及推断, 应该和前文类似, 是Delegate的依赖, 不太明白
以及最后的动态多播代理
基本同单播实现
同时, 这里PropertyFlags值添加一个BlueprintAssignable发生了变化, 多了CPF_BlueprintAssignable
属性篇 第十五节
至此, 多数常见的数据类型的反射信息就分析过一篇了.
可能存在没有分析的内容(看不懂).
可能存在没有分析到的数据类型(赖或者不常用)
自己总结概况整理一下, 很多地方都是相同的.
属性篇 第十六节
最后的最后, 是最后一种情况, 如果有很多属性呢? 如果和C++普通的属性混在一起呢?
是不是很熟悉呢? 只是重复定义并在数组里面加了一个值
至此, 反射系列关于参数相关的告一段落, 中间缺失的内容之后会视情况补上.
总共十六小节, 从GAObject04到GAObject28, 这么多个类, 希望一步一步跟做.
嗯, 虽然, 估计, 实际上, 应该不会有几个人跟着做(手动狗头)
结语
- 这是本周应该更的, 由于昨天修复旧文章代理相关内容, 估计函数反射相关的到下周了
- 本文中有些内容有缺失的地方, 可能会在之后找到对应资料, 或者有合适位置的时候再展开分析
- 骗赞了, 骗评论了.