当前位置: 首页 > news >正文

单页网站模板wap智慧团建登录不上

单页网站模板wap,智慧团建登录不上,网页源代码查看,威海网站建设whhlUE5反射系统分析#xff08;一#xff09;generated.h GENERATED_BODYenumstructclassinterface总结Reference UE5的反射系统代码相比于UE4有不少改动。最近在阅读UE4反射系统分析的相关文章的同时#xff0c;参照UE5的代码#xff0c;分析UE5的反射系统实现#xff0c;正… UE5反射系统分析一generated.h GENERATED_BODYenumstructclassinterface总结Reference UE5的反射系统代码相比于UE4有不少改动。最近在阅读UE4反射系统分析的相关文章的同时参照UE5的代码分析UE5的反射系统实现正好也能进一步消化和理解这一套框架的思想。 我们先把最常用的几种类型以最简单的形式放在一个文件MyClass.h里。 // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include CoreMinimal.h #include UObject/Object.h #include MyClass.generated.hUENUM() enum class EMyEnum : uint8 {MY_Dance,MY_Rain,MY_Song };USTRUCT() struct REFLECTION_API FMyStruct {GENERATED_BODY() };UCLASS() class REFLECTION_API UMyClass : public UObject {GENERATED_BODY() };UINTERFACE() class UMyInterface : public UInterface {GENERATED_BODY() };class REFLECTION_API IMyInterface {GENERATED_BODY() };众所周知UE会根据代码中的宏自动生成反射代码可以在项目的Intermediate\Build\Win64\UnrealEditor\Inc\Reflection\UHT目录下找到生成的文件可以看到有两个文件分别是MyClass.genertated.h和MyClass.gen.cpp。这两个文件中的代码很多我们先不急着看先从我们自己写的MyClass.h看起再一路顺藤摸瓜。 GENERATED_BODY GENERATED_BODY()宏通常放在类的定义中表示该类需要参与UE的反射系统。这个宏定义在ObjectMacros.h中 // This pair of macros is used to help implement GENERATED_BODY() and GENERATED_USTRUCT_BODY() #define BODY_MACRO_COMBINE_INNER(A,B,C,D) A##B##C##D #define BODY_MACRO_COMBINE(A,B,C,D) BODY_MACRO_COMBINE_INNER(A,B,C,D) #define GENERATED_BODY(...) BODY_MACRO_COMBINE(CURRENT_FILE_ID,_,__LINE__,_GENERATED_BODY);可以看出这个宏的作用就是将CURRENT_FILE_ID当前文件的ID和当前行号__LINE__以及后缀_GENERATED_BODY组合成一个唯一的标识符。这个标识符在生成的代码中会被用来区分不同的类型。既然是文件ID了那么它的值应该在MyClass.generated.h中就能找到。 #undef CURRENT_FILE_ID #define CURRENT_FILE_ID FID_Projects_Reflection_Source_Reflection_MyClass_hMyClass.h中有4个GENERATED_BODY()宏分别在FMyStruct、UMyClass、UMyInterface和IMyInterface中。在MyClass.generated.h中可以看到这四个宏被替换成了 #define FID_Projects_Reflection_Source_Reflection_MyClass_h_20_GENERATED_BODY #define FID_Projects_Reflection_Source_Reflection_MyClass_h_26_GENERATED_BODY #define FID_Projects_Reflection_Source_Reflection_MyClass_h_32_GENERATED_BODY #define FID_Projects_Reflection_Source_Reflection_MyClass_h_37_GENERATED_BODY而且这4个宏的定义还不太一样 #define FID_Projects_Reflection_Source_Reflection_MyClass_h_20_GENERATED_BODY \friend struct Z_Construct_UScriptStruct_FMyStruct_Statics; \static class UScriptStruct* StaticStruct();#define FID_Projects_Reflection_Source_Reflection_MyClass_h_26_GENERATED_BODY \ PRAGMA_DISABLE_DEPRECATION_WARNINGS \ public: \FID_Projects_Reflection_Source_Reflection_MyClass_h_26_INCLASS_NO_PURE_DECLS \FID_Projects_Reflection_Source_Reflection_MyClass_h_26_ENHANCED_CONSTRUCTORS \ private: \ PRAGMA_ENABLE_DEPRECATION_WARNINGS#define FID_Projects_Reflection_Source_Reflection_MyClass_h_32_GENERATED_BODY \PRAGMA_DISABLE_DEPRECATION_WARNINGS \FID_Projects_Reflection_Source_Reflection_MyClass_h_32_GENERATED_UINTERFACE_BODY() \FID_Projects_Reflection_Source_Reflection_MyClass_h_32_ENHANCED_CONSTRUCTORS \ private: \PRAGMA_ENABLE_DEPRECATION_WARNINGS#define FID_Projects_Reflection_Source_Reflection_MyClass_h_37_GENERATED_BODY \ PRAGMA_DISABLE_DEPRECATION_WARNINGS \ public: \FID_Projects_Reflection_Source_Reflection_MyClass_h_32_INCLASS_IINTERFACE_NO_PURE_DECLS \ private: \ PRAGMA_ENABLE_DEPRECATION_WARNINGS 可见反射系统需要先在头文件中插入一些生成代码才能辅助UE得到各种类型的反射信息。不过enum似乎是一个例外enum类型并不需要GENERATED_BODY()宏。那么enum类型应该是最简单得到就先从它开始分析。 enum 在MyClass.generated.h的结尾处可以找到与enum相关的几行代码 #define FOREACH_ENUM_EMYENUM(op) \op(EMyEnum::MY_Dance) \op(EMyEnum::MY_Rain) \op(EMyEnum::MY_Song) enum class EMyEnum : uint8; template struct TIsUEnumClassEMyEnum { enum { Value true }; }; template REFLECTION_API UEnum* StaticEnumEMyEnum();FOREACH_ENUM_XXX是一个UE生成的辅助宏用于遍历枚举类型的所有值。它的参数op是一个宏参数表示对每个枚举值执行的操作。在UE源代码中也可以找到这个宏的实际用例 // Texture.cpp #ifndef CASE_ENUM_TO_TEXT #define CASE_ENUM_TO_TEXT(txt) case txt: return TEXT(#txt); #endifconst TCHAR* UTexture::GetTextureGroupString(TextureGroup InGroup) {switch (InGroup){FOREACH_ENUM_TEXTUREGROUP(CASE_ENUM_TO_TEXT)}return TEXT(TEXTUREGROUP_World); }通过该宏可以方便地把enum的名称转换为字符串。 TIsUEnumClass就是一个模板类用于判断一个类型是否是UE的枚举类型。它的Value成员变量为true表示是枚举类型。 StaticEnum就是负责获取enum类型反射信息的最终函数它的实现在MyClass.gen.cpp中 static FEnumRegistrationInfo Z_Registration_Info_UEnum_EMyEnum; static UEnum* EMyEnum_StaticEnum() {if (!Z_Registration_Info_UEnum_EMyEnum.OuterSingleton){Z_Registration_Info_UEnum_EMyEnum.OuterSingleton GetStaticEnum(Z_Construct_UEnum_Reflection_EMyEnum, (UObject*)Z_Construct_UPackage__Script_Reflection(), TEXT(EMyEnum));}return Z_Registration_Info_UEnum_EMyEnum.OuterSingleton; } template REFLECTION_API UEnum* StaticEnumEMyEnum() {return EMyEnum_StaticEnum(); }可以看到StaticEnum函数会调用GetStaticEnum函数来获取枚举类型的反射信息这个函数内部是一个static变量的惰性初始化只有第一次调用时会创建一个UEnum对象并将其存储在OuterSingleton中。之后的调用就直接返回这个对象。具体UEnum对象的创建流程我们先放到后面再说。 struct MyClass.generated.h中与FMyStruct相关的代码如下 #define FID_Projects_Reflection_Source_Reflection_MyClass_h_20_GENERATED_BODY \friend struct Z_Construct_UScriptStruct_FMyStruct_Statics; \static class UScriptStruct* StaticStruct();template REFLECTION_API UScriptStruct* StaticStructstruct FMyStruct();相较于enumUE还为struct生成了成员函数版本的StaticStruct在MyClass.gen.cpp中可以看到模板函数的版本实际上调用的也是成员函数版本 static FStructRegistrationInfo Z_Registration_Info_UScriptStruct_MyStruct; class UScriptStruct* FMyStruct::StaticStruct() {if (!Z_Registration_Info_UScriptStruct_MyStruct.OuterSingleton){Z_Registration_Info_UScriptStruct_MyStruct.OuterSingleton GetStaticStruct(Z_Construct_UScriptStruct_FMyStruct, (UObject*)Z_Construct_UPackage__Script_Reflection(), TEXT(MyStruct));}return Z_Registration_Info_UScriptStruct_MyStruct.OuterSingleton; } template REFLECTION_API UScriptStruct* StaticStructFMyStruct() {return FMyStruct::StaticStruct(); }StaticStruct的实现与StaticEnum类似也是通过GetStaticStruct函数来获取结构体的反射信息。这个函数同样是一个static变量的惰性初始化第一次调用时会创建一个UScriptStruct对象并将其存储在OuterSingleton中。 class 与UMyClass相关的代码就比较多了 #define FID_Projects_Reflection_Source_Reflection_MyClass_h_26_INCLASS_NO_PURE_DECLS \ private: \static void StaticRegisterNativesUMyClass(); \friend struct Z_Construct_UClass_UMyClass_Statics; \ public: \DECLARE_CLASS(UMyClass, UObject, COMPILED_IN_FLAGS(0), CASTCLASS_None, TEXT(/Script/Reflection), NO_API) \DECLARE_SERIALIZER(UMyClass)#define FID_Projects_Reflection_Source_Reflection_MyClass_h_26_ENHANCED_CONSTRUCTORS \/** Standard constructor, called after all reflected properties have been initialized */ \NO_API UMyClass(const FObjectInitializer ObjectInitializer FObjectInitializer::Get()); \ private: \/** Private move- and copy-constructors, should never be used */ \UMyClass(UMyClass); \UMyClass(const UMyClass); \ public: \DECLARE_VTABLE_PTR_HELPER_CTOR(NO_API, UMyClass); \DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER(UMyClass); \DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(UMyClass) \NO_API virtual ~UMyClass();#define FID_Projects_Reflection_Source_Reflection_MyClass_h_23_PROLOG #define FID_Projects_Reflection_Source_Reflection_MyClass_h_26_GENERATED_BODY \ PRAGMA_DISABLE_DEPRECATION_WARNINGS \ public: \FID_Projects_Reflection_Source_Reflection_MyClass_h_26_INCLASS_NO_PURE_DECLS \FID_Projects_Reflection_Source_Reflection_MyClass_h_26_ENHANCED_CONSTRUCTORS \ private: \ PRAGMA_ENABLE_DEPRECATION_WARNINGStemplate REFLECTION_API UClass* StaticClassclass UMyClass();对于class类型UE生成的代码包含了更多的宏定义。首先是StaticRegisterNativesUMyClass这个函数在MyClass.gen.cpp中实现 void UMyClass::StaticRegisterNativesUMyClass() { }这里似乎很奇怪它居然是一个空函数不过其实这个函数是负责注册类的成员函数由于这里的class是空类所以才是空函数。 接下来的DECLARE_CLASS和DECLARE_SERIALIZER是UE定义在引擎中的宏。DECLARE_CLASS宏定义了类的各种信息最常用到的StaticClass就在其中而DECLARE_SERIALIZER宏则用于定义该类的序列化支持。 StaticClass的实现同样也是利用了惰性初始化只不过这次是存储在InnerSingleton中 #define IMPLEMENT_CLASS_NO_AUTO_REGISTRATION(TClass) \FClassRegistrationInfo Z_Registration_Info_UClass_##TClass; \UClass* TClass::GetPrivateStaticClass() \{ \if (!Z_Registration_Info_UClass_##TClass.InnerSingleton) \{ \/* this could be handled with templates, but we want it external to avoid code bloat */ \GetPrivateStaticClassBody( \StaticPackage(), \(TCHAR*)TEXT(#TClass) 1 ((StaticClassFlags CLASS_Deprecated) ? 11 : 0), \Z_Registration_Info_UClass_##TClass.InnerSingleton, \StaticRegisterNatives##TClass, \sizeof(TClass), \alignof(TClass), \TClass::StaticClassFlags, \TClass::StaticClassCastFlags(), \TClass::StaticConfigName(), \(UClass::ClassConstructorType)InternalConstructorTClass, \(UClass::ClassVTableHelperCtorCallerType)InternalVTableHelperCtorCallerTClass, \UOBJECT_CPPCLASS_STATICFUNCTIONS_FORCLASS(TClass), \TClass::Super::StaticClass, \TClass::WithinClass::StaticClass \); \} \return Z_Registration_Info_UClass_##TClass.InnerSingleton; \}再往下就是和构造函数相关的宏了。首先纳入UE反射系统的类默认构造函数和拷贝构造函数都是private的只有一个public的接受const FObjectInitializer参数的构造函数。这个函数的实现就是调用了基类的构造函数 UMyClass::UMyClass(const FObjectInitializer ObjectInitializer) : Super(ObjectInitializer) {}也就是说如果使用的是GENERATED_BODY我们没有办法实现对象的构造函数也就没办法调用自定义的逻辑。 interface 与class类似interface的生成代码也比较多 #define FID_Projects_Reflection_Source_Reflection_MyClass_h_32_ENHANCED_CONSTRUCTORS \/** Standard constructor, called after all reflected properties have been initialized */ \NO_API UMyInterface(const FObjectInitializer ObjectInitializer FObjectInitializer::Get()); \ private: \/** Private move- and copy-constructors, should never be used */ \UMyInterface(UMyInterface); \UMyInterface(const UMyInterface); \ public: \DECLARE_VTABLE_PTR_HELPER_CTOR(NO_API, UMyInterface); \DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER(UMyInterface); \DEFINE_ABSTRACT_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(UMyInterface) \NO_API virtual ~UMyInterface();#define FID_Projects_Reflection_Source_Reflection_MyClass_h_32_GENERATED_UINTERFACE_BODY() \ private: \static void StaticRegisterNativesUMyInterface(); \friend struct Z_Construct_UClass_UMyInterface_Statics; \ public: \DECLARE_CLASS(UMyInterface, UInterface, COMPILED_IN_FLAGS(CLASS_Abstract | CLASS_Interface), CASTCLASS_None, TEXT(/Script/Reflection), NO_API) \DECLARE_SERIALIZER(UMyInterface)#define FID_Projects_Reflection_Source_Reflection_MyClass_h_32_GENERATED_BODY \PRAGMA_DISABLE_DEPRECATION_WARNINGS \FID_Projects_Reflection_Source_Reflection_MyClass_h_32_GENERATED_UINTERFACE_BODY() \FID_Projects_Reflection_Source_Reflection_MyClass_h_32_ENHANCED_CONSTRUCTORS \ private: \PRAGMA_ENABLE_DEPRECATION_WARNINGS#define FID_Projects_Reflection_Source_Reflection_MyClass_h_32_INCLASS_IINTERFACE_NO_PURE_DECLS \ protected: \virtual ~IMyInterface() {} \ public: \typedef UMyInterface UClassType; \typedef IMyInterface ThisClass; \virtual UObject* _getUObject() const { return nullptr; }#define FID_Projects_Reflection_Source_Reflection_MyClass_h_29_PROLOG #define FID_Projects_Reflection_Source_Reflection_MyClass_h_37_GENERATED_BODY \ PRAGMA_DISABLE_DEPRECATION_WARNINGS \ public: \FID_Projects_Reflection_Source_Reflection_MyClass_h_32_INCLASS_IINTERFACE_NO_PURE_DECLS \ private: \ PRAGMA_ENABLE_DEPRECATION_WARNINGStemplate REFLECTION_API UClass* StaticClassclass UMyInterface();大部分内容和class差不多我们从DECLARE_CLASS的传参中可以推断出一些参数的含义例如第二个参数UInterface表示它是UMyInterface的基类而第三个参数COMPILED_IN_FLAGS(CLASS_Abstract | CLASS_Interface)则表示这是一个抽象类和接口类。 总结 我们大致分析了generated.h中的生成代码对代码中的不同宏和函数有了一个初步的了解。接下来我们需要深入到MyClass.gen.cpp中看看它们的具体实现以及在反射系统中的用途和调用的时机。 Reference [1] 《InsideUE4》UObject三类型系统设定和结构 [2] UE5反射系统笔记一 [3] 深入研究虚幻4反射系统实现原理一 [4] UE 反射实现分析反射代码生成一 [5] UObject 的 FObjectInitializer 构造函数的调用
http://www.hkea.cn/news/14292209/

相关文章:

  • 企业网站无线端怎么做北京简盟产品设计有限公司
  • 关键词搜索网站公司网站开发流程
  • 怎么做网站推广佳木斯上海沪琛品牌营销策划有限公司
  • 辽宁省建设工程信息网归哪里管seo怎么去优化网站
  • 省住房和城乡建设厅网站网站建设好找工作
  • 之路网站建设许昌网站开发公司
  • dedecms建设慕课网站oa厂家排名
  • 东莞网站制作咨询祥奔科技怎样做阿里巴巴网站
  • 汽车服务站建站流程wordpress优势
  • 长沙网站设计哪里好推广网站详细教程
  • 网站建设功能解说简单的网站设计
  • 网站备案服务码口令是什么意思济南建设工程
  • wordpress网站设置关键词设置怎样建官方网站
  • 建设部网站社保联网广州设计网站
  • 在做网站的公司做网站运营犯法吗网站如何被百度收录
  • 网站建设微信文章企业门户网站数据库设计
  • 重庆微信网站网站建设平台报价
  • 中文网站设计最近七天的新闻大事
  • 手机网站建设公外包公司的优势和劣势
  • 网站建设配图怎么判断一个网站做的好
  • 深圳市建网站乐清网站设计公司哪家好
  • 雅安建设局网站百度开放云 wordpress
  • 浙江人工智能建站系统软件做网站 还是淘宝店
  • 柳州做网站公司wordpress怎么添加用户中心页面
  • 免费空间网站网站设计画布规范1680
  • 做请帖网站医院网站后台模板
  • 做网站路由器映射外网全国企业公示信息公示网官网
  • 电脑优化青岛市做网站优化
  • asp网站建设教案兰坪建设公司网站
  • 安徽省工程建设信息官方网站wordpress免登录付费阅读