在Unreal中创建一个继承UObject的类时,默认会导入一个头文件BaseRole.generated.h,它在LearnCode\Intermediate\Build\Win64\UnrealEditor\Inc\LearnCode\UHT目录下由UHT生成BaseRole.generated.h,该目录下还有BaseRole.gen.cpp,
// BaseRole.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "BaseRole.generated.h"
UCLASS() //LINE 9
class LEARNCODE_API ABaseRole : public AActor
{
GENERATED_BODY() //LINE 12
public:
// Sets default values for this actor's properties
ABaseRole();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
// BaseRole.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "BaseRole.h"
// Sets default values
ABaseRole::ABaseRole()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void ABaseRole::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ABaseRole::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
调试UnrealBuildTool启动参数 -Target=”LearnCode Win64 Development” -Project=”D:\TrainWorkSpace\LearnCode\LearnCode.uproject” -WaitMutex -FromMsBuild
生成generated.h流程
//Engine\Source\Programs\UnrealBuildTool
UnrealBuildTool.cs Main(string[] ArgumentsArray)
UnrealHeaderToolMode.cs ExecuteAsync(CommandLineArguments Arguments, ILogger Logger)
//Engine\Source\Programs\Shared\EpicGames.UHT
UhtSession.cs Run(string manifestFilePath)
UhtCodeGenerator.cs CodeGenerator(IUhtExportFactory factory)
UClass()宏
// ObjectMacros.h
#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 UCLASS(...) BODY_MACRO_COMBINE(CURRENT_FILE_ID,_,__LINE__,_PROLOG)
GENERATED_BODY()宏
// ObjectMacros.h
#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);
#define GENERATED_USTRUCT_BODY(...) GENERATED_BODY()
#define GENERATED_UCLASS_BODY(...) GENERATED_BODY_LEGACY()
#define GENERATED_UINTERFACE_BODY(...) GENERATED_BODY_LEGACY()
#define GENERATED_IINTERFACE_BODY(...) GENERATED_BODY_LEGACY()
BaseRole.generated.h
// Copyright Epic Games, Inc. All Rights Reserved.
/*===========================================================================
Generated code exported from UnrealHeaderTool.
DO NOT modify this manually! Edit the corresponding .h files instead!
===========================================================================*/
// IWYU pragma: private, include "BaseRole.h"
#include "UObject/ObjectMacros.h"
#include "UObject/ScriptMacros.h"
PRAGMA_DISABLE_DEPRECATION_WARNINGS
#ifdef LEARNCODE_BaseRole_generated_h
#error "BaseRole.generated.h already included, missing '#pragma once' in BaseRole.h"
#endif
#define LEARNCODE_BaseRole_generated_h
#define FID_LearnCode_Source_LearnCode_BaseRole_h_12_INCLASS_NO_PURE_DECLS \
private: \
static void StaticRegisterNativesABaseRole(); \
friend struct Z_Construct_UClass_ABaseRole_Statics; \
public: \
DECLARE_CLASS(ABaseRole, AActor, COMPILED_IN_FLAGS(0 | CLASS_Config), CASTCLASS_None, TEXT("/Script/LearnCode"), NO_API) \
DECLARE_SERIALIZER(ABaseRole)
#define FID_LearnCode_Source_LearnCode_BaseRole_h_12_ENHANCED_CONSTRUCTORS \
private: \
/** Private move- and copy-constructors, should never be used */ \
ABaseRole(ABaseRole&&); \
ABaseRole(const ABaseRole&); \
public: \
DECLARE_VTABLE_PTR_HELPER_CTOR(NO_API, ABaseRole); \
DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER(ABaseRole); \
DEFINE_DEFAULT_CONSTRUCTOR_CALL(ABaseRole) \
NO_API virtual ~ABaseRole();
#define FID_LearnCode_Source_LearnCode_BaseRole_h_9_PROLOG
#define FID_LearnCode_Source_LearnCode_BaseRole_h_12_GENERATED_BODY \
PRAGMA_DISABLE_DEPRECATION_WARNINGS \
public: \
FID_LearnCode_Source_LearnCode_BaseRole_h_12_INCLASS_NO_PURE_DECLS \
FID_LearnCode_Source_LearnCode_BaseRole_h_12_ENHANCED_CONSTRUCTORS \
private: \
PRAGMA_ENABLE_DEPRECATION_WARNINGS
template<> LEARNCODE_API UClass* StaticClass<class ABaseRole>();
#undef CURRENT_FILE_ID
#define CURRENT_FILE_ID FID_LearnCode_Source_LearnCode_BaseRole_h
UClass展开后是FID_LearnCode_Source_LearnCode_BaseRole_h_9_PROLOG,GENERATED_BODY展开后是FID_LearnCode_Source_LearnCode_BaseRole_h_12_GENERATED_BODY,其展开FID_LearnCode_Source_LearnCode_BaseRole_h_12_INCLASS_NO_PURE_DECLS和FID_LearnCode_Source_LearnCode_BaseRole_h_12_ENHANCED_CONSTRUCTORS。
static void StaticRegisterNativesABaseRole()是空函数。
Z_Construct_UClass_ABaseRole_Statics结构体下面介绍。
DECLARE_CLASS(ABaseRole, AActor, COMPILED_IN_FLAGS(0 | CLASS_Config), CASTCLASS_None, TEXT("/Script/LearnCode"), NO_API)
DECLARE_CLASS()宏
// ObjectMacros.h
#define DECLARE_CLASS( TClass, TSuperClass, TStaticFlags, TStaticCastFlags, TPackage, TRequiredAPI ) \
private: \
TClass& operator=(TClass&&); \
TClass& operator=(const TClass&); \
TRequiredAPI static UClass* GetPrivateStaticClass(); \
public: \
/** Bitwise union of #EClassFlags pertaining to this class.*/ \
static constexpr EClassFlags StaticClassFlags=EClassFlags(TStaticFlags); \
/** Typedef for the base class () */ \
typedef TSuperClass Super;\
/** Typedef for . */ \
typedef TClass ThisClass;\
/** Returns a UClass object representing this class at runtime */ \
inline static UClass* StaticClass() \
{ \
return GetPrivateStaticClass(); \
} \
/** Returns the package this class belongs in */ \
inline static const TCHAR* StaticPackage() \
{ \
return TPackage; \
} \
/** Returns the static cast flags for this class */ \
inline static EClassCastFlags StaticClassCastFlags() \
{ \
return TStaticCastFlags; \
} \
/** For internal use only; use StaticConstructObject() to create new objects. */ \
inline void* operator new(const size_t InSize, EInternal InInternalOnly, UObject* InOuter = (UObject*)GetTransientPackage(), FName InName = NAME_None, EObjectFlags InSetFlags = RF_NoFlags) \
{ \
return StaticAllocateObject(StaticClass(), InOuter, InName, InSetFlags); \
} \
/** For internal use only; use StaticConstructObject() to create new objects. */ \
inline void* operator new( const size_t InSize, EInternal* InMem ) \
{ \
return (void*)InMem; \
} \
/* Eliminate V1062 warning from PVS-Studio while keeping MSVC and Clang happy. */ \
inline void operator delete(void* InMem) \
{ \
::operator delete(InMem); \
}
// Implement the GetPrivateStaticClass and the registration info but do not auto register the class.
// This is primarily used by UnrealHeaderTool
#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)InternalConstructor<TClass>, \
(UClass::ClassVTableHelperCtorCallerType)InternalVTableHelperCtorCaller<TClass>, \
UOBJECT_CPPCLASS_STATICFUNCTIONS_FORCLASS(TClass), \
&TClass::Super::StaticClass, \
&TClass::WithinClass::StaticClass \
); \
} \
return Z_Registration_Info_UClass_##TClass.InnerSingleton; \
}
StaticClass()里调用GetPrivateStaticClass,最终在GetPrivateStaticClassBody里构造UClass,大约3700个左右
//Engine\Source\Runtime\CoreUObject\Private\UObject\Class.cpp
void GetPrivateStaticClassBody(
const TCHAR* PackageName,
const TCHAR* Name,
UClass*& ReturnClass,
void(*RegisterNativeFunc)(),
uint32 InSize,
uint32 InAlignment,
EClassFlags InClassFlags,
EClassCastFlags InClassCastFlags,
const TCHAR* InConfigName,
UClass::ClassConstructorType InClassConstructor,
UClass::ClassVTableHelperCtorCallerType InClassVTableHelperCtorCaller,
FUObjectCppClassStaticFunctions&& InCppClassStaticFunctions,
UClass::StaticClassFunctionType InSuperClassFn,
UClass::StaticClassFunctionType InWithinClassFn
)
{
#if WITH_RELOAD
if (IsReloadActive() && GetActiveReloadType() != EActiveReloadType::Reinstancing)
{
UPackage* Package = FindPackage(NULL, PackageName);
if (Package)
{
ReturnClass = FindObject<UClass>((UObject *)Package, Name);
if (ReturnClass)
{
if (ReturnClass->HotReloadPrivateStaticClass(
InSize,
InClassFlags,
InClassCastFlags,
InConfigName,
InClassConstructor,
InClassVTableHelperCtorCaller,
FUObjectCppClassStaticFunctions(InCppClassStaticFunctions),
InSuperClassFn(),
InWithinClassFn()
))
{
// Register the class's native functions.
RegisterNativeFunc();
}
return;
}
else
{
UE_LOG(LogClass, Log, TEXT("Could not find existing class %s in package %s for reload, assuming new or modified class"), Name, PackageName);
}
}
else
{
UE_LOG(LogClass, Log, TEXT("Could not find existing package %s for reload of class %s, assuming a new package."), PackageName, Name);
}
}
#endif
ReturnClass = (UClass*)GUObjectAllocator.AllocateUObject(sizeof(UClass), alignof(UClass), true);
ReturnClass = ::new (ReturnClass)
UClass
(
EC_StaticConstructor,
Name,
InSize,
InAlignment,
InClassFlags,
InClassCastFlags,
InConfigName,
EObjectFlags(RF_Public | RF_Standalone | RF_Transient | RF_MarkAsNative | RF_MarkAsRootSet),
InClassConstructor,
InClassVTableHelperCtorCaller,
MoveTemp(InCppClassStaticFunctions)
);
check(ReturnClass);
InitializePrivateStaticClass(
InSuperClassFn(),
ReturnClass,
InWithinClassFn(),
PackageName,
Name
);
// Register the class's native functions.
RegisterNativeFunc();
}
DECLARE_SERIALIZER宏 ,系列化对象 DECLARE_SERIALIZER(ABaseRole)
// ObjectMacros.h
#define DECLARE_SERIALIZER( TClass ) \
friend FArchive &operator<<( FArchive& Ar, TClass*& Res ) \
{ \
return Ar << (UObject*&)Res; \
} \
friend void operator<<(FStructuredArchive::FSlot InSlot, TClass*& Res) \
{ \
InSlot << (UObject*&)Res; \
}
移动构造函数ABaseRole(ABaseRole&&)和拷贝函数ABaseRole(const ABaseRole&)被禁用。
如果是GENERATED_BODY_LEGACY 需要自己实现这个构造函数 NO_API UTestBTTask_Log(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); \
接着是二个和 hot-reload相关的宏
DECLARE_VTABLE_PTR_HELPER_CTOR(NO_API, ABaseRole);
// ObjectMacros.h
#define DECLARE_VTABLE_PTR_HELPER_CTOR(API, TClass) \
/** DO NOT USE. This constructor is for internal usage only for hot-reload purposes. */ \
API TClass(FVTableHelper& Helper);
DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER(ABaseRole);
// ObjectMacros.h
#define DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER_DUMMY() \
static UObject* __VTableCtorCaller(FVTableHelper& Helper) \
{ \
return nullptr; \
}
#if WITH_RELOAD && !CHECK_PUREVIRTUALS
#define DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER(TClass) \
static UObject* __VTableCtorCaller(FVTableHelper& Helper) \
{ \
return new (EC_InternalUseOnlyConstructor, (UObject*)GetTransientPackage(), NAME_None, RF_NeedLoad | RF_ClassDefaultObject | RF_TagGarbageTemp) TClass(Helper); \
}
#else // WITH_RELOAD && !CHECK_PUREVIRTUALS
#define DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER(TClass) \
DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER_DUMMY()
#endif // WITH_RELOAD && !CHECK_PUREVIRTUALS
构造函数 DEFINE_DEFAULT_CONSTRUCTOR_CALL(ABaseRole)
// ObjectMacros.h
#define DEFINE_DEFAULT_CONSTRUCTOR_CALL(TClass) \
static void __DefaultConstructor(const FObjectInitializer& X) { new((EInternal*)X.GetObj())TClass; }
//Class.h
/**
* Helper template to call the default constructor for a class
*/
template<class T>
void InternalConstructor( const FObjectInitializer& X )
{
T::__DefaultConstructor(X);
}
析构函数 NO_API virtual ~ABaseRole();
接下来是具体实现
BaseRole.gen.cpp
// Copyright Epic Games, Inc. All Rights Reserved.
/*===========================================================================
Generated code exported from UnrealHeaderTool.
DO NOT modify this manually! Edit the corresponding .h files instead!
===========================================================================*/
#include "UObject/GeneratedCppIncludes.h"
#include "LearnCode/BaseRole.h"
PRAGMA_DISABLE_DEPRECATION_WARNINGS
void EmptyLinkFunctionForGeneratedCodeBaseRole() {}
// Begin Cross Module References
ENGINE_API UClass* Z_Construct_UClass_AActor();
LEARNCODE_API UClass* Z_Construct_UClass_ABaseRole();
LEARNCODE_API UClass* Z_Construct_UClass_ABaseRole_NoRegister();
UPackage* Z_Construct_UPackage__Script_LearnCode();
// End Cross Module References
// Begin Class ABaseRole
void ABaseRole::StaticRegisterNativesABaseRole()
{
}
IMPLEMENT_CLASS_NO_AUTO_REGISTRATION(ABaseRole);
UClass* Z_Construct_UClass_ABaseRole_NoRegister()
{
return ABaseRole::StaticClass();
}
struct Z_Construct_UClass_ABaseRole_Statics
{
#if WITH_METADATA
static constexpr UECodeGen_Private::FMetaDataPairParam Class_MetaDataParams[] = {
{ "IncludePath", "BaseRole.h" },
{ "ModuleRelativePath", "BaseRole.h" },
};
#endif // WITH_METADATA
static UObject* (*const DependentSingletons[])();
static constexpr FCppClassTypeInfoStatic StaticCppClassTypeInfo = {
TCppClassTypeTraits<ABaseRole>::IsAbstract,
};
static const UECodeGen_Private::FClassParams ClassParams;
};
UObject* (*const Z_Construct_UClass_ABaseRole_Statics::DependentSingletons[])() = {
(UObject* (*)())Z_Construct_UClass_AActor,
(UObject* (*)())Z_Construct_UPackage__Script_LearnCode,
};
static_assert(UE_ARRAY_COUNT(Z_Construct_UClass_ABaseRole_Statics::DependentSingletons) < 16);
const UECodeGen_Private::FClassParams Z_Construct_UClass_ABaseRole_Statics::ClassParams = {
&ABaseRole::StaticClass,
"Engine",
&StaticCppClassTypeInfo,
DependentSingletons,
nullptr,
nullptr,
nullptr,
UE_ARRAY_COUNT(DependentSingletons),
0,
0,
0,
0x009000A4u,
METADATA_PARAMS(UE_ARRAY_COUNT(Z_Construct_UClass_ABaseRole_Statics::Class_MetaDataParams), Z_Construct_UClass_ABaseRole_Statics::Class_MetaDataParams)
};
UClass* Z_Construct_UClass_ABaseRole()
{
if (!Z_Registration_Info_UClass_ABaseRole.OuterSingleton)
{
UECodeGen_Private::ConstructUClass(Z_Registration_Info_UClass_ABaseRole.OuterSingleton, Z_Construct_UClass_ABaseRole_Statics::ClassParams);
}
return Z_Registration_Info_UClass_ABaseRole.OuterSingleton;
}
template<> LEARNCODE_API UClass* StaticClass<ABaseRole>()
{
return ABaseRole::StaticClass();
}
DEFINE_VTABLE_PTR_HELPER_CTOR(ABaseRole);
ABaseRole::~ABaseRole() {}
// End Class ABaseRole
// Begin Registration
struct Z_CompiledInDeferFile_FID_LearnCode_Source_LearnCode_BaseRole_h_Statics
{
static constexpr FClassRegisterCompiledInInfo ClassInfo[] = {
{ Z_Construct_UClass_ABaseRole, ABaseRole::StaticClass, TEXT("ABaseRole"), &Z_Registration_Info_UClass_ABaseRole, CONSTRUCT_RELOAD_VERSION_INFO(FClassReloadVersionInfo, sizeof(ABaseRole), 4034982424U) },
};
};
static FRegisterCompiledInInfo Z_CompiledInDeferFile_FID_LearnCode_Source_LearnCode_BaseRole_h_2509242738(TEXT("/Script/LearnCode"),
Z_CompiledInDeferFile_FID_LearnCode_Source_LearnCode_BaseRole_h_Statics::ClassInfo, UE_ARRAY_COUNT(Z_CompiledInDeferFile_FID_LearnCode_Source_LearnCode_BaseRole_h_Statics::ClassInfo),
nullptr, 0,
nullptr, 0);
// End Registration
PRAGMA_ENABLE_DEPRECATION_WARNINGS
DependentSingletons 该对象处理时需要先处理的依赖
InOuterRegister :Z_Construct_UClass_ABaseRole 函数指针 UECodeGen_Private::ConstructUClass 通过Z_Construct_UClass_ABaseRole_Statics::ClassParams主要是为Uclass初始一些属性
InInnerRegister: ABaseRole::StaticClass 函数指针 实际调用GetPrivateStaticClass 通过GetPrivateStaticClassBody 创建UClass
ReturnClass = (UClass*)GUObjectAllocator.AllocateUObject(sizeof(UClass), alignof(UClass), true);
ReturnClass = ::new (ReturnClass)
UClass
(xx,xx)
placement new语法:所谓placement new就是在用户指定的内存位置上构建新的对象,这个构建过程不需要额外分配内存,只需要调用对象的构造函数即可
::new (placement_address) Type(arguments);
static FRegisterCompiledInInfo 记录注册UClass的信息,数据最终存在Registrations中,它是在Main函数之前完成的。
//UObjectBase.cpp
/**
* Helper class to perform registration of object information. It blindly forwards a call to RegisterCompiledInInfo
*/
struct FRegisterCompiledInInfo
{
template <typename ... Args>
FRegisterCompiledInInfo(Args&& ... args)
{
RegisterCompiledInInfo(std::forward<Args>(args)...);
}
};
void RegisterCompiledInInfo(const TCHAR* PackageName, const FClassRegisterCompiledInInfo* ClassInfo, size_t NumClassInfo, const FStructRegisterCompiledInInfo* StructInfo, size_t NumStructInfo, const FEnumRegisterCompiledInInfo* EnumInfo, size_t NumEnumInfo)
{
LLM_SCOPE(ELLMTag::UObject);
for (size_t Index = 0; Index < NumClassInfo; ++Index)
{
const FClassRegisterCompiledInInfo& Info = ClassInfo[Index];
RegisterCompiledInInfo(Info.OuterRegister, Info.InnerRegister, PackageName, Info.Name, *Info.Info, Info.VersionInfo);
}
for (size_t Index = 0; Index < NumStructInfo; ++Index)
{
const FStructRegisterCompiledInInfo& Info = StructInfo[Index];
RegisterCompiledInInfo(Info.OuterRegister, PackageName, Info.Name, *Info.Info, Info.VersionInfo);
if (Info.CreateCppStructOps != nullptr)
{
UScriptStruct::DeferCppStructOps(FTopLevelAssetPath(FName(PackageName), FName(Info.Name)), (UScriptStruct::ICppStructOps*)Info.CreateCppStructOps());
}
}
for (size_t Index = 0; Index < NumEnumInfo; ++Index)
{
const FEnumRegisterCompiledInInfo& Info = EnumInfo[Index];
RegisterCompiledInInfo(Info.OuterRegister, PackageName, Info.Name, *Info.Info, Info.VersionInfo);
}
}
void RegisterCompiledInInfo(class UClass* (*InOuterRegister)(), class UClass* (*InInnerRegister)(), const TCHAR* InPackageName, const TCHAR* InName, FClassRegistrationInfo& InInfo, const FClassReloadVersionInfo& InVersionInfo)
{
check(InOuterRegister);
check(InInnerRegister);
FClassDeferredRegistry::AddResult result = FClassDeferredRegistry::Get().AddRegistration(InOuterRegister, InInnerRegister, InPackageName, InName, InInfo, InVersionInfo);
#if WITH_RELOAD
if (result == FClassDeferredRegistry::AddResult::ExistingChanged && !IsReloadActive())
{
// Class exists, this can only happen during hot-reload or live coding
UE_LOG(LogUObjectBase, Fatal, TEXT("Trying to recreate changed class '%s' outside of hot reload and live coding!"), InName);
}
#endif
FString NoPrefix(UObjectBase::RemoveClassPrefix(InName));
NotifyRegistrationEvent(InPackageName, *NoPrefix, ENotifyRegistrationType::NRT_Class, ENotifyRegistrationPhase::NRP_Added, (UObject * (*)())(InOuterRegister), false);
NotifyRegistrationEvent(InPackageName, *(FString(DEFAULT_OBJECT_PREFIX) + NoPrefix), ENotifyRegistrationType::NRT_ClassCDO, ENotifyRegistrationPhase::NRP_Added, (UObject * (*)())(InOuterRegister), false);
}
//DeferredRegistry.h
AddResult AddRegistration(TType* (*InOuterRegister)(), TType* (*InInnerRegister)(), const TCHAR* InPackageName, const TCHAR* InName, TInfo& InInfo, const TVersion& InVersion)
{
#if WITH_RELOAD
const FPackageAndNameKey Key = FPackageAndNameKey{ InPackageName, InName };
TInfo** ExistingInfo = InfoMap.Find(Key);
bool bHasChanged = !ExistingInfo || (*ExistingInfo)->ReloadVersionInfo != InVersion;
InInfo.ReloadVersionInfo = InVersion;
TType* OldSingleton = ExistingInfo ? ((*ExistingInfo)->InnerSingleton ? (*ExistingInfo)->InnerSingleton : (*ExistingInfo)->OuterSingleton) : nullptr;
bool bAdd = true;
if (ExistingInfo)
{
if (IReload* Reload = GetActiveReloadInterface())
{
bAdd = Reload->GetEnableReinstancing(bHasChanged);
}
if (bAdd)
{
if (!bHasChanged)
{
// With live coding, the existing might be the same as the new info.
// We still invoke the copy method to allow UClasses to clear the singletons.
UpdateSingletons(InInfo, **ExistingInfo);
}
*ExistingInfo = &InInfo;
}
}
else
{
InfoMap.Add(Key, &InInfo);
}
if (bAdd)
{
Registrations.Add(FRegistrant{ InOuterRegister, InInnerRegister, InPackageName, &InInfo, OldSingleton, bHasChanged });
}
return ExistingInfo == nullptr ? AddResult::New : (bHasChanged ? AddResult::ExistingChanged : AddResult::ExistingNoChange);
#else
Registrations.Add(FRegistrant{ InOuterRegister, InInnerRegister, InPackageName, &InInfo });
return AddResult::New;
#endif
}
加载CoreUObject时候处理之前注册的所有UClass,
//LaunchEngineLoop.cpp
bool FEngineLoop::LoadCoreModules()
{
// Always attempt to load CoreUObject. It requires additional pre-init which is called from its module's StartupModule method.
#if WITH_COREUOBJECT
// Always register the UObjects callback for VNI and general consistency with the callbacks ProcessNewlyLoadedUObjects calls.
RegisterProcessNewlyLoadedUObjects();
return FModuleManager::Get().LoadModule(TEXT("CoreUObject")) != nullptr;
#else
return true;
#endif
}
//CoreNative.cpp
class FCoreUObjectModule : public FDefaultModuleImpl
{
virtual void StartupModule() override
{
// Register all classes that have been loaded so far. This is required for CVars to work.
UClassRegisterAllCompiledInClasses();
void InitUObject();
FCoreDelegates::OnInit.AddStatic(InitUObject);
}
}
//UObjectBase.cpp
/** Register all loaded classes */
void UClassRegisterAllCompiledInClasses()
{
#if WITH_RELOAD
TArray<UClass*> AddedClasses;
#endif
SCOPED_BOOT_TIMING("UClassRegisterAllCompiledInClasses");
LLM_SCOPE(ELLMTag::UObject);
FClassDeferredRegistry& Registry = FClassDeferredRegistry::Get();
Registry.ProcessChangedObjects();
for (const FClassDeferredRegistry::FRegistrant& Registrant : Registry.GetRegistrations())
{
UClass* RegisteredClass = FClassDeferredRegistry::InnerRegister(Registrant);
#if WITH_RELOAD
if (IsReloadActive() && Registrant.OldSingleton == nullptr)
{
AddedClasses.Add(RegisteredClass);
}
#endif
}
#if WITH_RELOAD
if (AddedClasses.Num() > 0)
{
FCoreUObjectDelegates::ReloadAddedClassesDelegate.Broadcast(AddedClasses);
PRAGMA_DISABLE_DEPRECATION_WARNINGS
FCoreUObjectDelegates::RegisterHotReloadAddedClassesDelegate.Broadcast(AddedClasses);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
#endif
}
ProcessNewlyLoadedUObjects处理加载module后用到的Uclass
//UObjectBase.cpp
void RegisterProcessNewlyLoadedUObjects()
{
static bool bHasRegistered = false;
if (!bHasRegistered)
{
bHasRegistered = true;
FModuleManager::Get().OnProcessLoadedObjectsCallback().AddStatic(ProcessNewlyLoadedUObjects);
}
}
void ProcessNewlyLoadedUObjects(FName Package, bool bCanProcessNewlyLoadedObjects)
{
SCOPED_BOOT_TIMING("ProcessNewlyLoadedUObjects");
#if USE_PER_MODULE_UOBJECT_BOOTSTRAP
if (Package != NAME_None)
{
UObjectReleaseModuleRegistrants(Package);
}
#endif
if (!bCanProcessNewlyLoadedObjects)
{
FCoreUObjectDelegates::CompiledInUObjectsRegisteredDelegate.Broadcast(Package, ECompiledInUObjectsRegisteredStatus::Delayed);
return;
}
LLM_SCOPE(ELLMTag::UObject);
DECLARE_SCOPE_CYCLE_COUNTER(TEXT("ProcessNewlyLoadedUObjects"), STAT_ProcessNewlyLoadedUObjects, STATGROUP_ObjectVerbose);
FPackageDeferredRegistry& PackageRegistry = FPackageDeferredRegistry::Get();
FClassDeferredRegistry& ClassRegistry = FClassDeferredRegistry::Get();
FStructDeferredRegistry& StructRegistry = FStructDeferredRegistry::Get();
FEnumDeferredRegistry& EnumRegistry = FEnumDeferredRegistry::Get();
PackageRegistry.ProcessChangedObjects(true);
StructRegistry.ProcessChangedObjects();
EnumRegistry.ProcessChangedObjects();
UClassRegisterAllCompiledInClasses();
bool bNewUObjects = false;
TArray<UClass*> AllNewClasses;
while (GFirstPendingRegistrant ||
ClassRegistry.HasPendingRegistrations() ||
StructRegistry.HasPendingRegistrations() ||
EnumRegistry.HasPendingRegistrations())
{
bNewUObjects = true;
UObjectProcessRegistrants();
UObjectLoadAllCompiledInStructs();
FCoreUObjectDelegates::CompiledInUObjectsRegisteredDelegate.Broadcast(Package, ECompiledInUObjectsRegisteredStatus::PreCDO);
UObjectLoadAllCompiledInDefaultProperties(AllNewClasses);
}
FCoreUObjectDelegates::CompiledInUObjectsRegisteredDelegate.Broadcast(Package, ECompiledInUObjectsRegisteredStatus::PostCDO);
#if WITH_RELOAD
IReload* Reload = GetActiveReloadInterface();
if (Reload != nullptr)
{
UClassReplaceReloadClasses(); // Legacy
PackageRegistry.NotifyReload(*Reload);
EnumRegistry.NotifyReload(*Reload);
StructRegistry.NotifyReload(*Reload);
ClassRegistry.NotifyReload(*Reload);
Reload->Reinstance();
}
#endif
PackageRegistry.EmptyRegistrations();
EnumRegistry.EmptyRegistrations();
StructRegistry.EmptyRegistrations();
ClassRegistry.EmptyRegistrations();
if (TMap<UObjectBase*, FPendingRegistrantInfo>& PendingRegistrants = FPendingRegistrantInfo::GetMap(); PendingRegistrants.IsEmpty())
{
PendingRegistrants.Empty();
}
if (bNewUObjects && !GIsInitialLoad)
{
for (UClass* Class : AllNewClasses)
{
// Assemble reference token stream for garbage collection/ RTGC.
if (!Class->HasAnyFlags(RF_ClassDefaultObject) && !Class->HasAnyClassFlags(CLASS_TokenStreamAssembled))
{
Class->AssembleReferenceTokenStream();
}
}
}
}
将注册的Class信息转化为真正的对象
/**
* Convert a boot-strap registered class into a real one, add to uobject array, etc
*
* @param UClassStaticClass Now that it is known, fill in UClass::StaticClass() as the class
*/
void UObjectBase::DeferredRegister(UClass *UClassStaticClass,const TCHAR* PackageName,const TCHAR* InName)
{
check(UObjectInitialized());
// Set object properties.
UPackage* Package = CreatePackage(PackageName);
check(Package);
Package->SetPackageFlags(PKG_CompiledIn);
OuterPrivate = Package;
check(UClassStaticClass);
check(!ClassPrivate);
ClassPrivate = UClassStaticClass;
// Add to the global object table.
AddObject(FName(InName), EInternalObjectFlags::None);
// At this point all compiled-in objects should have already been fully constructed so it's safe to remove the NotFullyConstructed flag
// which was set in FUObjectArray::AllocateUObjectIndex (called from AddObject)
GUObjectArray.IndexToObject(InternalIndex)->ClearFlags(EInternalObjectFlags::PendingConstruction);
// Make sure that objects disregarded for GC are part of root set.
check(!GUObjectArray.IsDisregardForGC(this) || GUObjectArray.IndexToObject(InternalIndex)->IsRootSet());
UE_LOG(LogUObjectBootstrap, Verbose, TEXT("UObjectBase::DeferredRegister %s %s"), PackageName, InName);
}
EXPAND_MACRO 宏展开工具
#ifndef _CRT_STRINGIZE
#define _CRT_STRINGIZE_(x) #x
#define _CRT_STRINGIZE(x) _CRT_STRINGIZE_(x)
#endif
//Expands to macro:
#define EXPAND_MACRO(x) __pragma(message(__FILE__ _CRT_STRINGIZE((__LINE__): \nmacro\t)#x" expands to:\n" _CRT_STRINGIZE(x)))
EXPAND_MACRO(FID_LearnCode_Source_LearnCode_BaseRole_h_9_PROLOG);
EXPAND_MACRO(FID_LearnCode_Source_LearnCode_BaseRole_h_12_GENERATED_BODY);
读取反射信息
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "BaseRole")
int Level;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "BaseRole")
int Health;
UFUNCTION(BlueprintCallable, Category = "BaseRole")
void OnHit(int NewLevel);
void ABaseRole::OnHit(int NewLevel)
{
UE_LOG(LogTemp, Warning, TEXT("OnHit %d") , NewLevel);
}
// Called when the game starts or when spawned
void ABaseRole::BeginPlay()
{
Super::BeginPlay();
TArray<UObject*> Objects;
GetObjectsOfClass(UClass::StaticClass(), Objects);
UClass* Class = FindObject<UClass>(ANY_PACKAGE, TEXT("BaseRole"));
if (Class)
{
UE_LOG(LogTemp, Warning, TEXT("Class found: %s"), *Class->GetName());
for (const FProperty* Property = Class->PropertyLink; Property; Property = Property->PropertyLinkNext)
{
FName propertyName = Property->GetFName();
UE_LOG(LogTemp, Warning, TEXT("Property found: %s"), *propertyName.ToString());
}
const FProperty* LevelPro = Class->FindPropertyByName(TEXT("Level"));
int* ProValue = LevelPro->ContainerPtrToValuePtr<int>(this);
*ProValue = 1;
UFunction* Func = Class->FindFunctionByName(TEXT("OnHit"));
this->ProcessEvent(Func,ProValue);
for (TFieldIterator<UFunction> Fit(Class, EFieldIteratorFlags::IncludeSuper); Fit; ++Fit)
{
const UFunction* Function = *Fit;
UE_LOG(LogTemp, Log, TEXT( "Function Found: %s();" ), *Function->GetName());
for (TFieldIterator<FProperty> It(Function); It; ++It)
{
const FProperty* Property = *It;
UE_LOG(LogTemp, Log, TEXT( " Property Found: %s;" ), *Property->GetName());
UE_LOG(LogTemp, Log, TEXT( " Property Type: %s;" ), *Property->GetCPPType());
if (Property->GetPropertyFlags() & CPF_ReturnParm)
{
UE_LOG(LogTemp, Log, TEXT( " Property is Return Parm;" ));
}
}
}
TArray<UClass*> DerivedClasses;
GetDerivedClasses(Class, DerivedClasses);
UClass* SuperClass = Class->GetSuperClass();
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Class not found"));
}
}