UE4反射机制学习

参考资料:https://blog.csdn.net/mohuak/article/details/81913532?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase


UE4中反射用于什么情况?

#define UPROPERTY(...)
#define UFUNCTION(...)
#define USTRUCT(...)
#define UMETA(...)
#define UPARAM(...)
#define UENUM(...)
#define UDELEGATE(...)

// 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)

// Include a redundant semicolon at the end of the generated code block, so that intellisense parsers can start parsing
// a new declaration if the line number/generated code is out of date.
#define GENERATED_BODY_LEGACY(...) BODY_MACRO_COMBINE(CURRENT_FILE_ID,_,__LINE__,_GENERATED_BODY_LEGACY);
#define GENERATED_BODY(...) BODY_MACRO_COMBINE(CURRENT_FILE_ID,_,__LINE__,_GENERATED_BODY);

当我们给变量/函数/类/结构体添加U###的时候,UHT就会帮助我们实现反射机制

C++与蓝图交互,UE4的变量回收系统,几乎UE4所有的Module都利用了反射机制


UBT和UHT介绍

UnrealBuildTool(UBT):UE4来编译各个模块之间的依赖

UnrealHeaderTool(UHT,C++编译器强化版):UE4 C++代码编译。UHT利用.generated.h信息生成C++反射代码。完成后,再调用普通的C++编译器

启动UE4编译时,UE4首先调用UHT,检索.h中的UCLASS、GENERATED_BODY、UPROPERTY、UFUNTION等关键字,然后生成generate.h和generate.cpp文件


生成阶段

helloworld.generated.h文件中

GENERATED_BODY

#define GENERATED_BODY_LEGACY(...) BODY_MACRO_COMBINE(CURRENT_FILE_ID,_,__LINE__,_GENERATED_BODY_LEGACY);

对于某个类的GENERATED_BODY来说,CURRENT_FILE_ID定义在该文件的.generated.h文件中

DECLARE_FUNCTION

  1. NavtiveFuncTest定义BlueprintNativeEvent,蓝图和C++均可以实现。在C++中实现的方法要加上NavtiveFuncTest_Implementation(),因为UBT内部已经实现这部分的定义?(理由见下)
  2. DECLARE_FUNCTION(execNavtiveFuncTest)。声明一个函数为execNavtiveFuncTest,会优先调用蓝图方法,如果不存在的话再调用C++的NavtiveFuncTest_Implementation()

DECLARE_CLASS

private: \
	static void StaticRegisterNativesAHelloGameMode(); \
	friend struct Z_Construct_UClass_AHelloGameMode_Statics; \
public: \
	DECLARE_CLASS(AHelloGameMode, AGameModeBase, COMPILED_IN_FLAGS(0 | CLASS_Transient), CASTCLASS_None, TEXT("/Script/helloworld"), NO_API) \
	DECLARE_SERIALIZER(AHelloGameMode)

Generated.cpp文件中

ProcessEvent

static FName NAME_AHelloGameMode_NavtiveFuncTest = FName(TEXT("NavtiveFuncTest"));
void AHelloGameMode::NavtiveFuncTest()
{
	ProcessEvent(FindFunctionChecked(NAME_AHelloGameMode_NavtiveFuncTest),NULL);
}

很明显,在.cpp文件中,NativeFuncTest函数已经被自动生成。因此对于都可用&&蓝图>C++优先级的情况下,需要加上_Implementablement来声明,否则会报错已经定义

IMPLEMENT_CLASS

MPLEMENT_CLASS(AHelloGameMode, 3705664059);
template<> HELLOWORLD_API UClass* StaticClass<AHelloGameMode>()
{
	return AHelloGameMode::StaticClass();
}

收集阶段(利用Static自动注册方式,将UCLASS登记,放进Array统一管理)

在收集阶段(上一阶段)在IMPLEMENT_CLASS和ConstructClass两个函数中静态声明了两个变量

#define IMPLEMENT_CLASS(TClass, TClassCrc) \
	static TClassCompiledInDefer<TClass> AutoInitialize##TClass(TEXT(#TClass), sizeof(TClass), TClassCrc); \

static FCompiledInDefer Z_CompiledInDefer_UClass_##TClass(Z_Construct_UClass_##TClass, &TClass::StaticClass, TEXT(TPackage), TEXT(#TClass), false);
  • TClassCompiledInDefer(调用UClassCompiledInDefer收集数据)是分配空间
  • FCompiledInDefer(调用UObjectCompiledInDefer收集数据),调用初始化函数
  • 并且将注册信息放入ClassInfo延迟注册,如果类太多,全部都要注册会很卡

void ProcessNewlyLoadedUObjects(FName Package, bool bCanProcessNewlyLoadedObjects)
{
	UClassRegisterAllCompiledInClasses();

	const TArray<UClass* (*)()>& DeferredCompiledInRegistration = GetDeferredCompiledInRegistration();
	const TArray<FPendingStructRegistrant>& DeferredCompiledInStructRegistration = GetDeferredCompiledInStructRegistration();
	const TArray<FPendingEnumRegistrant>& DeferredCompiledInEnumRegistration = GetDeferredCompiledInEnumRegistration();

	bool bNewUObjects = false;
	while (GFirstPendingRegistrant || DeferredCompiledInRegistration.Num() || DeferredCompiledInStructRegistration.Num() || DeferredCompiledInEnumRegistration.Num())
	{
		bNewUObjects = true;
		UObjectProcessRegistrants();
		UObjectLoadAllCompiledInStructs();
		UObjectLoadAllCompiledInDefaultProperties();
	}
}

ProcessNewlyLoadedUObjects用于注册类,结构体,枚举的反射信息

收集阶段

通过UClassCompiledInDefer收集

在Static Array里添加ClassInfo→Register()→StaticClass()→GetPrivateStaticClass()→GetPrivateStaticClassBody()

GetPrivateStaticClassBody():分配内存,

通过UObjectCompiledInDefer收集

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值