使用UE4的同学一定对"*.generated.h"这个名字不陌生。蓝图、HotReload等功能都依赖于反射机制。本文会从生成代码分析UE4的反射系统是如何实现的。
TOC
本文代码版本为UE4.21。
本文实际上是对照《Inside UE4》知乎专栏,分析源码的学习笔记。想要深入了解的可以去专栏。专栏地址为:
https://zhuanlan.zhihu.com/insideue4
不少语言都有反射系统。动态语言不说,很多工具都可以实现静态语言的反射。比较有名的就是Qt。
我们可以思考一下如果要我们自己实现一个C++的反射系统,将会如何实现?
当前C++实现反射的方案包括以下流派:
UE4定义了一系列的宏,来帮助开发者将自定义的字段和函数添加至反射系统。
先来看一段典型的UE4的反射声明代码:
// 一定要声明UCLASS
UCLASS()
class MYGAME_API UMyClass : public UObject
{
GENERATED_BODY()
public:
// 定义一个可反射的函数
UFUNCTION(BluprintCallable)
void MyFunc();
private:
// 定义一个可反射的变量
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(AllowPrivateAccess = "true"))
int MyIntValue;
}
先来看看类图:
可以使用的宏定义:
反射宏名称 | 作用 |
---|---|
UCLASS | 告诉UE这个类是一个反射类。类必须派生自UObject |
USTRUCT | 可以不用派生自UObject。不支持GC,也不能包含函数 |
UPROPERTY | 定义一个反射的变量 |
UFUNCTION | 定义一个反射的函数 |
UENUM | 告诉UE这是一个反射的枚举类。支持enum, enum class, enum namespace |
UINTERFACE | 定义一个反射接口类,只能包含函数 |
UMETA | 反射的一些元数据定义,可以通过标签定义一些该变量的属性 |
UPARAM | 定义函数的参数属性。主要就是显示名字和Ref属性 |
UDELEGATE | 告诉UE这是一个可反射的delegate(很少用到) |
具体解析的流程在FHeaderParser::ParseHeader
中。采用的是传统的LL分析法手写代码,而并没有采用LR生成代码。好处就是可以灵活地写逻辑。(光这一个文件就1w行。。)
可以稍微看一下解析的核心代码:
// 解析代码
ECompilationResult::Type FHeaderParser::ParseHeader(FClasses& AllClasses, FUnrealSourceFile* SourceFile)
{
// ...
// 解析一个Statement
while (CompileStatement(AllClasses, DelegatesToFixup))
{
// ...
StatementsParsed++;
}
// ...
}
// 获取并解析一个Token
bool FHeaderParser::CompileStatement(FClasses& AllClasses, TArray<UDelegateFunction*>& DelegatesToFixup)
{
// Get a token and compile it.
FToken Token;
if( !GetToken(Token, true) )
{
// End of file.
return false;
}
else if (!CompileDeclaration(AllClasses, DelegatesToFixup, Token))
{
FError::Throwf(TEXT("'%s': Bad command or expression"), Token.Identifier );
}
return true;
}
// 解析所获取的Token
bool FHeaderParser::CompileDeclaration(FClasses& AllClasses, TArray<UDelegateFunction*>& DelegatesToFixup, FToken& Token)
{
// ...
if (Token.Matches(TEXT("UCLASS"), ESearchCase::CaseSensitive))
{
// ...
UClass* Class = CompileClassDeclaration(AllClasses);
// ...
}
if (Token.Matches(TEXT("UINTERFACE"), ESearchCase::CaseSensitive))
{
// ...
CompileInterfaceDeclaration(AllClasses);
// ...
}
// 以及其它所有的宏的匹配。。
}
第一步解析完所有的反射信息之后,要如何注入到程序中去呢?答案就是:生成代码。
相信有过UE4开发经验的同学都对"*.generated.h"这个名字不陌生。这就是UE4的UHT(Unreal Header Tool)模块扫描之后生成的代码。会生成.h和.cpp两个文件:
.generated.h
文件:重载各种操作符函数,声明各种构造函数。.gen.cpp
文件:单例实现,构造UClass(提取信息并注册)我们可以通过一个简单的UClass,来查看生成的代码。我们创建一个文件:MyObject.h
// MyObject.h
#include "MyObject.generated.h"
UENUM()
enum class EMyEnum
{
Enm1 = 1,
Enm2 = 2,
};
USTRUCT()
struct FMyStruct
{
GENERATED_BODY()
UPROPERTY()
float StructProperty;
};
UINTERFACE()
class UMyInterface : public UInterface
{
GENERATED_BODY()
}
class IMyInterface
{
GENERATED_BODY()
public:
UFUNCTION()
virtual void InterfaceFunction();
}
UCLASS()
class THEMYPROJECT_API UMyObject : public UObject
{
GENERATED_BODY()
public:
UFUNCTION()
void ClassFunction() {};
UPROPERTY()
int ClassProperty;
};
这个简单的类,麻雀虽小五脏俱全,包含了UCLASS、USTRUCT、UINTERFACE、UENUM、UFUNCTION、UPROPERTY六种类型。那么反射系统生成出来的代码是怎样的呢?
首先来看MyObject.generated.h
。很多行,这里分块阐述。有兴趣的同学可以用上述示例代码来生成反射代码亲自查看。
第一个宏定义如下:
#define MyProject_Source_MyProject_MyObject_h_19_GENERATED_BODY \
friend struct Z_Construct_UScriptStruct_FMyStruct_Statics; \
THEMYPROJECT_API static class UScriptStruct* StaticStruct();
可以看到宏名构成:
路径名_行号_GENERATE_BODY
我们再来看GENERATE_BODY宏。
#define CURRENT_FILE_ID MyProject_Source_MyProject_MyObject_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 GENERATED_BODY(...) BODY_MACRO_COMBINE(CURRENT_FILE_ID,_,__LINE__,_GENERATED_BODY);
完全展开正是:
MyProject_Source_MyProject_MyObject_h_19_GENERATED_BODY
果不其然!
UE4为每个类生成了一个专门的反射数据收集类,以友元类的方式来访问类信息。
根据行号,可以知道这是FMyStruct类的生成宏代码,也就是USTRUCT的生成宏代码。
类似的,UClass也是一样的路数。利用ReSharper的宏展开功能(强烈推荐ReSharper 2019来开发UE4,会对UE4做专门的提示和补全优化),可以看到我们定义的类,最终被转换为了一系列反射代码。
这里为了阅读流畅性,生成的代码放在附录中。
这里有两点值得注意:
好,那生成的类总得运行吧?那会在什么地方调用呢?
答案就是:通过static构造函数来在全局main函数之前,执行反射系统的收集逻辑。
关键就在于.gen.cpp代码中的IMPLEMENT_CLASS宏。这个宏展开之后如下:
static TClassCompiledInDefer<UMyObject> AutoInitializeUMyObject(L"UMyObject", sizeof(UMyObject), 2973152461);
// TClassCompiledInDefer的构造函数,会把类信息添加到DeferredClassRegistration数组中
TClassCompiledInDefer(const TCHAR* InName, SIZE_T InClassSize, uint32 InCrc)
: FFieldCompiledInInfo(InClassSize, InCrc)
{
UClassCompiledInDefer(this, InName, InClassSize, InCrc);
}
void UClassCompiledInDefer(FFieldCompiledInInfo* ClassInfo, const TCHAR* Name, SIZE_T ClassSize, uint32 Crc)
{
// ...
GetDeferredClassRegistration().Add(ClassInfo);
}
在CoreNative.cpp的StartupModule函数中,会依次处理这些收集到的类信息。
TArray<FFieldCompiledInInfo*>& DeferredClassRegistration = GetDeferredClassRegistration();
for (const FFieldCompiledInInfo* Class : DeferredClassRegistration)
{
UClass* RegisteredClass = Class->Register();
// ...
}
// Register会调用类的StaticClass函数
下面我们来通过这些代码,依次解读不同反射宏的实现原理。
首先是通过设置友元类的方式来访问原始定义的类,收集原始类的数据。
friend struct Z_Construct_UClass_UMyObject_Statics;
这个类的定义则放在了MyObject.gen.cpp中。
struct Z_Construct_UClass_UMyObject_Statics
{
static UObject* (*const DependentSingletons[])();
static const FClassFunctionLinkInfo FuncInfo[];
#if WITH_METADATA
static const UE4CodeGen_Private::FMetaDataPairParam Class_MetaDataParams[];
#endif
#if WITH_METADATA
static const UE4CodeGen_Private::FMetaDataPairParam NewProp_ClassProperty_MetaData[];
#endif
static const UE4CodeGen_Private::FUnsizedIntPropertyParams NewProp_ClassProperty;
static const UE4CodeGen_Private::FPropertyParamsBase* const PropPointers[];
static const FCppClassTypeInfoStatic StaticCppClassTypeInfo;
static const UE4CodeGen_Private::FClassParams ClassParams;
};
这个数据类只是负责收集原始类的信息。注意到全都是const的变量。会通过const提前初始化的特性来直接生成类参数。
例如,收集这个类的属性信息的代码:
// ClassProperty变量的信息
// 这里使用了初始化列表来直接对没有虚表的类进行初始化
const UE4CodeGen_Private::FUnsizedIntPropertyParams Z_Construct_UClass_UMyObject_Statics::NewProp_ClassProperty = {
UE4CodeGen_Private::EPropertyClass::Int, "ClassProperty", RF_Public | RF_Transient | RF_MarkAsNative,
(EPropertyFlags)0x0010000000000000, 1, nullptr, STRUCT_OFFSET(UMyObject, ClassProperty), METADATA_PARAMS(
Z_Construct_UClass_UMyObject_Statics::NewProp_ClassProperty_MetaData,
ARRAY_COUNT(Z_Construct_UClass_UMyObject_Statics::NewProp_ClassProperty_MetaData))
};
// 只有ClassProperty一个变量,因此数组中只有一个值
const UE4CodeGen_Private::FPropertyParamsBase* const Z_Construct_UClass_UMyObject_Statics::PropPointers[] = {
(const UE4CodeGen_Private::FPropertyParamsBase*)&Z_Construct_UClass_UMyObject_Statics::NewProp_ClassProperty,
};
所有类的关键信息,都会通过构造ClassParam来生成。
const UE4CodeGen_Private::FClassParams Z_Construct_UClass_UMyObject_Statics::ClassParams = {
&UMyObject::StaticClass, // ClassNoregisterFunc
DependentSingletons, // DependencySingletonFuncArray
ARRAY_COUNT(DependentSingletons), // NumDependencySingletons
0x001000A0u, // ClassFlags
FuncInfo, // FunctionLinkArray
ARRAY_COUNT(FuncInfo), // NumFunctions
Z_Construct_UClass_UMyObject_Statics::PropPointers, // PropertyArray
ARRAY_COUNT(Z_Construct_UClass_UMyObject_Statics::PropPointers), // NumProperties
nullptr, // ClassConfigNameUTF8
&StaticCppClassTypeInfo, // CppClassInfo
nullptr, // ImplementedInterfaceArray
0, // NumImplementedInterfaces
Z_Construct_UClass_UMyObject_Statics::Class_MetaDataParams, // MetaDataArray
(sizeof(ArrayCountHelper(Z_Construct_UClass_UMyObject_Statics::Class_MetaDataParams)) - 1), // NumMetaData
};
这些类信息,会通过调用StaticClass传给反射系统:
inline static UClass* StaticClass() { return GetPrivateStaticClass(); }
// 这里会将各种类的信息参数传给反射系统。
UClass* UMyObject::GetPrivateStaticClass()
{
static UClass* PrivateStaticClass = 0;
if (!PrivateStaticClass)
{
GetPrivateStaticClassBody(StaticPackage(), // PackageName
(TCHAR*)L"UMyObject" + 1 + ((StaticClassFlags & CLASS_Deprecated) ? 11 : 0), // Name
PrivateStaticClass, // ReturnClass
StaticRegisterNativesUMyObject, // RegisterNativeFunc
sizeof(UMyObject), // InSize
(EClassFlags)UMyObject::StaticClassFlags, // InClassFlags
UMyObject::StaticClassCastFlags(), // InClassCastFlags
UMyObject::StaticConfigName(), // InConfigName
(UClass::ClassConstructorType)InternalConstructor<UMyObject>, // InClassConstructor
(UClass::ClassVTableHelperCtorCallerType)InternalVTableHelperCtorCaller<UMyObject>,
// InClassVTableHelperCtorCaller
&UMyObject::AddReferencedObjects, // InClassAddReferencedObjects
&UMyObject::Super::StaticClass, // InSuperClassFn
&UMyObject::WithinClass::StaticClass); // InWithinClassFn
}
return PrivateStaticClass;
};
(UClass是最典型的反射,因此将代码放在这里详细讲。后续不会那么详细。PS:相信后续详细也没有同学想再认真看吧。。)
先来看看定义在UClass中的属性是如何收集的。
在上面代码中,我们定义了一个属性:int ClassProperty
。
生成的代码都放在.gen.cpp文件中。
仔细观察之前UClass的数据收集类Z_Construct_UClass_UMyObject_Statics,可以看到定义了属性信息:
struct Z_Construct_UClass_UMyObject_Statics
{
// ...
static const UE4CodeGen_Private::FUnsizedIntPropertyParams NewProp_ClassProperty; // 为ClassProperty属性生成的信息
static const UE4CodeGen_Private::FPropertyParamsBase* const PropPointers[]; // 所有属性的信息数组
// ...
};
这里会对每个属性单独生成单独的信息。这里只定义了一个属性,因此只有一条信息。
const UE4CodeGen_Private::FUnsizedIntPropertyParams Z_Construct_UClass_UMyObject_Statics::NewProp_ClassProperty = {
UE4CodeGen_Private::EPropertyClass::Int, // NameUTF8
"ClassProperty", // RepNotifyFuncUTF8
RF_Public | RF_Transient | RF_MarkAsNative, // PropertyFlags
(EPropertyFlags) 0x0010000000000000, // Flags
1, // ObjectFlags
nullptr, // ArrayDim
STRUCT_OFFSET(UMyObject, ClassProperty), // Offset
METADATA_PARAMS(
Z_Construct_UClass_UMyObject_Statics::NewProp_ClassProperty_MetaData,
ARRAY_COUNT(Z_Construct_UClass_UMyObject_Statics::NewProp_ClassProperty_MetaData)) // MetaDataArray and NumMetaData
};
然后添加到数组中:
const UE4CodeGen_Private::FPropertyParamsBase* const Z_Construct_UClass_UMyObject_Statics::PropPointers[] = {
(const UE4CodeGen_Private::FPropertyParamsBase*)&Z_Construct_UClass_UMyObject_Statics::NewProp_ClassProperty,
};
这样就完成了UPROPERTY的收集
UFUNCTION的收集比UPROPERTY稍微复杂一点,因为多出了两点:
下面继续依次来看这两点:
生成的参数数组会放在FuncParam中。最终,也是通过UClass的收集数据类将信息传给反射系统。
struct Z_Construct_UClass_UMyObject_Statics
{
// ...
static const FClassFunctionLinkInfo FuncInfo[];
// ...
};
收集的原理和UCLASS大致是一样的。区别主要在于两点:
GENERATED_BODY注入的代码如下:
struct FMyStruct
{
friend struct Z_Construct_UScriptStruct_FMyStruct_Statics;
static class UScriptStruct* StaticStruct();;
float StructProperty;
};
生成的数据收集类结构如下:
struct Z_Construct_UScriptStruct_FMyStruct_Statics
{
#if WITH_METADATA
static const UE4CodeGen_Private::FMetaDataPairParam Struct_MetaDataParams[];
#endif
static void* NewStructOps();
#if WITH_METADATA
static const UE4CodeGen_Private::FMetaDataPairParam NewProp_StructProperty_MetaData[];
#endif
static const UE4CodeGen_Private::FFloatPropertyParams NewProp_StructProperty;
static const UE4CodeGen_Private::FPropertyParamsBase* const PropPointers[];
static const UE4CodeGen_Private::FStructParams ReturnStructParams;
};
可以看到,与UClass相比,没有FuncInfo,也没有StaticCppClassTypeInfo类信息。
其它的机制,都是相同的。同样会通过StaticStruct函数来将信息传递给反射系统
UINTERFACE定义时就比较不一样,需要定义两个类,一个是UMyInterface类,继承UInterface,其中什么数据都没有。另一个是IMyInterface类,什么都不继承。
对于反射系统来说,一个接口和一个类的区别,主要有三点:
UMyInterface类生成的代码与UCLASS基本是一样的,只是声明了一个反射类。区别只是设置了ClassFlag为CLASS_Abstract和CLASS_Interface。
enum { StaticClassFlags=(CLASS_Abstract | CLASS_Interface | CLASS_Intrinsic) };
至于另一个类IMyInterface,其实也没有做些什么特殊的处理。只是将包装的函数实现放在了这个类中:
class IMyInterface
{
// ...
static void execInterfaceFunction(UObject* Context, FFrame& Stack, void* const Z_Param__Result)
{
Stack.Code += !!Stack.Code;;
{
;;
((ThisClass*)(Context))->InterfaceFunction();
};
}
// ...
}
而UMyInterface类构造传递的函数则是传递了IMyInterface类中定义的函数。
void UMyInterface::StaticRegisterNativesUMyInterface()
{
UClass* Class = UMyInterface::StaticClass();
static const FNameNativePtrPair Funcs[] = {
{"InterfaceFunction", &IMyInterface::execInterfaceFunction}, // 这里传递的函数是IMyInterface中的函数
};
FNativeFunctionRegistrar::RegisterFunctions(Class, Funcs, ARRAY_COUNT(Funcs));
}
这里不禁要思考:为什么要用两个类来实现呢?
因为接口是存在多继承的,一个类有可能继承多个接口。如果每个接口都是UObject,会出现菱形继承的情况。而菱形继承
会大大扩张虚表的大小,而且会造成二义性,调用基类的函数需要显示声明,这肯定是不现实的。
这个时候,UINTERFACE用两个类来实现,就可以避免菱形继承的问题。外部类如果要继承接口的话,只能继承IMyInterface类。
另外这里还有一点值得注意:如果一个类继承了UINTERFACE:
在InterfaceParams里面会传入多重继承的指针偏移offset(通过VTABLE_OFFSET获取)。
static const UE4CodeGen_Private::FImplementedInterfaceParams InterfaceParams[]=
{
{
Z_Construct_UClass_UMyInterface_NoRegister,//构造UMyInterface所属的UClass*函数指针
(int32)VTABLE_OFFSET(UMyClass, IMyInterface),//多重继承的指针偏移
false //是否是在蓝图实现
}
};
因为接口是使用多继承,因此需要通过指针偏移,来根据**Obj + Offset
**来获取接口地址调用接口函数。
最后是枚举的收集。这个不需要添加GENERATED_BODY宏,所有的代码都在.gen.cpp文件中生成。
会在构造的时候生成所有枚举值:
static const UE4CodeGen_Private::FEnumeratorParam Enumerators[] = {
{"EMyEnum::Enm1", (int64)EMyEnum::Enm1},
{"EMyEnum::Enm2", (int64)EMyEnum::Enm2},
};
同其他类型一样,也是通过构造Param传递给反射系统:
static const UE4CodeGen_Private::FEnumParams EnumParams = {
(UObject*(*)())Z_Construct_UPackage__Script_MyProject,
UE4CodeGen_Private::EDynamicType::NotDynamic,
"EMyEnum",
RF_Public | RF_Transient | RF_MarkAsNative,
nullptr,
(uint8)UEnum::ECppForm::EnumClass,
"EMyEnum",
Enumerators,
ARRAY_COUNT(Enumerators),
Enum_MetaDataParams, (sizeof(ArrayCountHelper(Enum_MetaDataParams)) - 1),
};
UE4CodeGen_Private::ConstructUEnum(ReturnEnum, EnumParams);
上面我们非常详细地分析了各种反射宏定义所生成的代码和数据收集流程。
前文说过,会在CoreNative.cpp的StartupModule函数中真正处理所有类的注册。
现在我们已经拿到了这些类数据了,那么怎么存储呢?
关键在于GetPrivateStaticClassBody函数。这个函数会在Register调用StaticClass的时候调用,主要会做以下几件事:
FPendingRegistrant\* PendingRegistration = new FPendingRegistrant(this);
PendingRegistrants.Add(this, FPendingRegistrantInfo(InName, PackageName));
if(GLastPendingRegistrant)
{
GLastPendingRegistrant->NextAutoRegister = PendingRegistration;
}
else
{
check(!GFirstPendingRegistrant);
GFirstPendingRegistrant = PendingRegistration;
}
GLastPendingRegistrant = PendingRegistration;
}
NativeFunctionLookupTable
中,添加函数指针。在所有类Register之后,所有数据信息都已经收集完毕。接下来就是在引擎的初始化时去使用这些收集的信息构造引擎中真正存储的结构树。
核心代码在这里,通过一个while循环来真正构造结构树。注意这里的循环条件是计算Num,因为使用的这些数组是有可能变化的,每次循环都需要重新计算一次Num。
void ProcessNewlyLoadedUObjects() {
//...
bool bNewUObjects = false;
while( GFirstPendingRegistrant || DeferredCompiledInRegistration.Num() || DeferredCompiledInStructRegistration.Num() || DeferredCompiledInEnumRegistration.Num() )
{
bNewUObjects = true;
UObjectProcessRegistrants(); // 处理所有UObject
UObjectLoadAllCompiledInStructs(); // 处理所有Enum和Struct
UObjectLoadAllCompiledInDefaultProperties(); // 构造CDO(Class Default Object)
}
//...
}
内部的结构会使用一个全局数组来存储所有Object。并会用一个UObjectHash结构来存储Name到UObject指针的关联关系。
这个UObjectHash结构也是专门优化过的特殊Hash结构。
使用了多个TMap来加速查找过程
// UObject哈希结构
class FUObjectHashTables
{
// ...
/** Hash sets */
TMap<int32, FHashBucket> Hash;
TMultiMap<int32, class UObjectBase*> HashOuter;
/** Map of object to their outers, used to avoid an object iterator to find such things. **/
TMap<UObjectBase*, FHashBucket> ObjectOuterMap;
TMap<UClass*, TSet<UObjectBase*> > ClassToObjectListMap;
TMap<UClass*, TSet<UClass*> > ClassToChildListMap;
// ...
}
注意一下Hash和HashOuter的Key,是特殊计算出来的int值。利用了FName的全局唯一性,保证每个FName的hash值不一样。
// 设置Number的核心代码
#define NAME_INTERNAL_TO_EXTERNAL(x) (x - 1)
#define NAME_EXTERNAL_TO_INTERNAL(x) (x + 1)
// 计算hash的函数
static FORCEINLINE int32 GetObjectHash(FName ObjName)
{
return (ObjName.GetComparisonIndex() ^ ObjName.GetNumber());
}
FHashBucket是一个用于处理哈希冲突的类。
本文从常用的反射实现方法入手,详细分析了UE4通过宏定义生成反射信息的机制,并详细分析了UE4各类型的反射生成代码,以及UE4内部是如何使用反射信息的。
对UE4反射信息机制的了解,有助于我们对UE4的特化C++有更深的认识。
笔者在项目中也通过UE4的反射系统,搭配Emmylua语法,实现了Lua中的UE4函数自动补全。有兴趣的同学可以参考这篇文章:
这里隐藏了所有#pragma warning的代码。所有宏替换为了展开代码。
原始代码:
#include "CoreMinimal.h"
#include "MyObject.generated.h"
UCLASS()
class THEMYPROJECT_API UMyObject : public UObject
{
GENERATED_BODY()
public:
UFUNCTION()
int ClassFunction(int IntParam) { };
UPROPERTY()
int ClassProperty;
};
展开GENERATED_BODY之后的代码:
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "UObject/ScriptMacros.h"
class THEMYPROJECT_API UMyObject : public UObject
{
public:
static void execClassFunction(UObject* Context, FFrame& Stack, void* const Z_Param__Result)
{
UIntProperty::TCppType Z_Param_IntParam = UIntProperty::GetDefaultPropertyValue();
Stack.StepCompiledIn<UIntProperty>(&Z_Param_IntParam);;
Stack.Code += !!Stack.Code;;
{
;;
*(int32*)Z_Param__Result = ((ThisClass*)(Context))->ClassFunction(Z_Param_IntParam);
};
}
private:
static void StaticRegisterNativesUMyObject();
friend struct Z_Construct_UClass_UMyObject_Statics;
public:
private:
UMyObject& operator=(UMyObject&&);
UMyObject& operator=(const UMyObject&);
static UClass* GetPrivateStaticClass();
public:
enum { StaticClassFlags=(0 | CLASS_Intrinsic) };
typedef UObject Super;
typedef UMyObject ThisClass;
inline static UClass* StaticClass() { return GetPrivateStaticClass(); }
inline static const TCHAR* StaticPackage() { return L"/Script/MyProject"; }
inline static EClassCastFlags StaticClassCastFlags() { return CASTCLASS_None; }
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);
}
inline void* operator new(const size_t InSize, EInternal* InMem) { return (void*)InMem; }
friend FArchive& operator<<(FArchive& Ar, UMyObject*& Res) { return Ar << (UObject*&)Res; }
friend void operator<<(FStructuredArchive::FSlot InSlot, UMyObject*& Res) { InSlot << (UObject*&)Res; }
UMyObject(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()) : Super(ObjectInitializer)
{
};
private:
UMyObject(UMyObject&&);
UMyObject(const UMyObject&);
public:
UMyObject(FVTableHelper& Helper);;
static UObject* __VTableCtorCaller(FVTableHelper& Helper) { return nullptr; };
static void __DefaultConstructor(const FObjectInitializer& X) { new((EInternal*)X.GetObj())UMyObject(X); }
private:
public:
int ClassFunction(int IntParam)
{
return 0;
};
int ClassProperty;
};
.gen.cpp文件:
#include "UObject/GeneratedCppIncludes.h"
#include "MyProject/MyObject.h"
void EmptyLinkFunctionForGeneratedCodeMyObject()
{
}
// Cross Module References
UClass* Z_Construct_UClass_UMyObject_NoRegister();
UClass* Z_Construct_UClass_UMyObject();
UClass* Z_Construct_UClass_UObject();
UPackage* Z_Construct_UPackage__Script_MyProject();
UFunction* Z_Construct_UFunction_UMyObject_ClassFunction();
// End Cross Module References
void UMyObject::StaticRegisterNativesUMyObject()
{
UClass* Class = UMyObject::StaticClass();
static const FNameNativePtrPair Funcs[] = {
{"ClassFunction", &UMyObject::execClassFunction},
};
FNativeFunctionRegistrar::RegisterFunctions(Class, Funcs, ARRAY_COUNT(Funcs));
}
struct Z_Construct_UFunction_UMyObject_ClassFunction_Statics
{
struct MyObject_eventClassFunction_Parms
{
int32 IntParam;
int32 ReturnValue;
};
static const UE4CodeGen_Private::FUnsizedIntPropertyParams NewProp_ReturnValue;
static const UE4CodeGen_Private::FUnsizedIntPropertyParams NewProp_IntParam;
static const UE4CodeGen_Private::FPropertyParamsBase* const PropPointers[];
#if WITH_METADATA
static const UE4CodeGen_Private::FMetaDataPairParam Function_MetaDataParams[];
#endif
static const UE4CodeGen_Private::FFunctionParams FuncParams;
};
const UE4CodeGen_Private::FUnsizedIntPropertyParams Z_Construct_UFunction_UMyObject_ClassFunction_Statics::
NewProp_ReturnValue = {
UE4CodeGen_Private::EPropertyClass::Int, "ReturnValue", RF_Public | RF_Transient | RF_MarkAsNative,
(EPropertyFlags)0x0010000000000580, 1, nullptr, STRUCT_OFFSET(MyObject_eventClassFunction_Parms, ReturnValue),
METADATA_PARAMS(nullptr, 0)
};
const UE4CodeGen_Private::FUnsizedIntPropertyParams Z_Construct_UFunction_UMyObject_ClassFunction_Statics::
NewProp_IntParam = {
UE4CodeGen_Private::EPropertyClass::Int, "IntParam", RF_Public | RF_Transient | RF_MarkAsNative,
(EPropertyFlags)0x0010000000000080, 1, nullptr, STRUCT_OFFSET(MyObject_eventClassFunction_Parms, IntParam),
METADATA_PARAMS(nullptr, 0)
};
const UE4CodeGen_Private::FPropertyParamsBase* const Z_Construct_UFunction_UMyObject_ClassFunction_Statics::PropPointers
[] = {
(const UE4CodeGen_Private::FPropertyParamsBase*)&Z_Construct_UFunction_UMyObject_ClassFunction_Statics::
NewProp_ReturnValue,
(const UE4CodeGen_Private::FPropertyParamsBase*)&Z_Construct_UFunction_UMyObject_ClassFunction_Statics::
NewProp_IntParam,
};
#if WITH_METADATA
const UE4CodeGen_Private::FMetaDataPairParam Z_Construct_UFunction_UMyObject_ClassFunction_Statics::
Function_MetaDataParams[] = {
{"ModuleRelativePath", "MyObject.h"},
};
#endif
const UE4CodeGen_Private::FFunctionParams Z_Construct_UFunction_UMyObject_ClassFunction_Statics::FuncParams = {
(UObject*(*)())Z_Construct_UClass_UMyObject, "ClassFunction", RF_Public | RF_Transient | RF_MarkAsNative, nullptr,
(EFunctionFlags)0x00020401, sizeof(MyObject_eventClassFunction_Parms),
Z_Construct_UFunction_UMyObject_ClassFunction_Statics::PropPointers,
ARRAY_COUNT(Z_Construct_UFunction_UMyObject_ClassFunction_Statics::PropPointers), 0, 0, METADATA_PARAMS(
Z_Construct_UFunction_UMyObject_ClassFunction_Statics::Function_MetaDataParams,
ARRAY_COUNT(Z_Construct_UFunction_UMyObject_ClassFunction_Statics::Function_MetaDataParams))
};
UFunction* Z_Construct_UFunction_UMyObject_ClassFunction()
{
static UFunction* ReturnFunction = nullptr;
if (!ReturnFunction)
{
UE4CodeGen_Private::ConstructUFunction(ReturnFunction,
Z_Construct_UFunction_UMyObject_ClassFunction_Statics::FuncParams);
}
return ReturnFunction;
}
UClass* Z_Construct_UClass_UMyObject_NoRegister()
{
return UMyObject::StaticClass();
}
struct Z_Construct_UClass_UMyObject_Statics
{
static UObject* (*const DependentSingletons[])();
static const FClassFunctionLinkInfo FuncInfo[];
#if WITH_METADATA
static const UE4CodeGen_Private::FMetaDataPairParam Class_MetaDataParams[];
#endif
#if WITH_METADATA
static const UE4CodeGen_Private::FMetaDataPairParam NewProp_ClassProperty_MetaData[];
#endif
static const UE4CodeGen_Private::FUnsizedIntPropertyParams NewProp_ClassProperty;
static const UE4CodeGen_Private::FPropertyParamsBase* const PropPointers[];
static const FCppClassTypeInfoStatic StaticCppClassTypeInfo;
static const UE4CodeGen_Private::FClassParams ClassParams;
};
UObject* (*const Z_Construct_UClass_UMyObject_Statics::DependentSingletons[])() = {
(UObject* (*)())Z_Construct_UClass_UObject,
(UObject* (*)())Z_Construct_UPackage__Script_MyProject,
};
const FClassFunctionLinkInfo Z_Construct_UClass_UMyObject_Statics::FuncInfo[] = {
{&Z_Construct_UFunction_UMyObject_ClassFunction, "ClassFunction"}, // 531444507
};
#if WITH_METADATA
const UE4CodeGen_Private::FMetaDataPairParam Z_Construct_UClass_UMyObject_Statics::Class_MetaDataParams[] = {
{"IncludePath", "MyObject.h"},
{"ModuleRelativePath", "MyObject.h"},
};
#endif
#if WITH_METADATA
const UE4CodeGen_Private::FMetaDataPairParam Z_Construct_UClass_UMyObject_Statics::NewProp_ClassProperty_MetaData[] = {
{"ModuleRelativePath", "MyObject.h"},
};
#endif
const UE4CodeGen_Private::FUnsizedIntPropertyParams Z_Construct_UClass_UMyObject_Statics::NewProp_ClassProperty = {
UE4CodeGen_Private::EPropertyClass::Int, "ClassProperty", RF_Public | RF_Transient | RF_MarkAsNative,
(EPropertyFlags)0x0010000000000000, 1, nullptr, STRUCT_OFFSET(UMyObject, ClassProperty), METADATA_PARAMS(
Z_Construct_UClass_UMyObject_Statics::NewProp_ClassProperty_MetaData,
ARRAY_COUNT(Z_Construct_UClass_UMyObject_Statics::NewProp_ClassProperty_MetaData))
};
const UE4CodeGen_Private::FPropertyParamsBase* const Z_Construct_UClass_UMyObject_Statics::PropPointers[] = {
(const UE4CodeGen_Private::FPropertyParamsBase*)&Z_Construct_UClass_UMyObject_Statics::NewProp_ClassProperty,
};
const FCppClassTypeInfoStatic Z_Construct_UClass_UMyObject_Statics::StaticCppClassTypeInfo = {
TCppClassTypeTraits<UMyObject>::IsAbstract,
};
const UE4CodeGen_Private::FClassParams Z_Construct_UClass_UMyObject_Statics::ClassParams = {
&UMyObject::StaticClass,
DependentSingletons, ARRAY_COUNT(DependentSingletons),
0x001000A0u,
FuncInfo, ARRAY_COUNT(FuncInfo),
Z_Construct_UClass_UMyObject_Statics::PropPointers, ARRAY_COUNT(Z_Construct_UClass_UMyObject_Statics::PropPointers),
nullptr,
&StaticCppClassTypeInfo,
nullptr, 0,
METADATA_PARAMS(Z_Construct_UClass_UMyObject_Statics::Class_MetaDataParams,
ARRAY_COUNT(Z_Construct_UClass_UMyObject_Statics::Class_MetaDataParams))
};
UClass* Z_Construct_UClass_UMyObject()
{
static UClass* OuterClass = nullptr;
if (!OuterClass)
{
UE4CodeGen_Private::ConstructUClass(OuterClass, Z_Construct_UClass_UMyObject_Statics::ClassParams);
}
return OuterClass;
}
static TClassCompiledInDefer<UMyObject> AutoInitializeUMyObject(L"UMyObject", sizeof(UMyObject), 3193407229);
UClass* UMyObject::GetPrivateStaticClass()
{
static UClass* PrivateStaticClass = 0;
if (!PrivateStaticClass)
{
GetPrivateStaticClassBody(StaticPackage(),
(TCHAR*)L"UMyObject" + 1 + ((StaticClassFlags & CLASS_Deprecated) ? 11 : 0),
PrivateStaticClass, StaticRegisterNativesUMyObject, sizeof(UMyObject),
(EClassFlags)UMyObject::StaticClassFlags, UMyObject::StaticClassCastFlags(),
UMyObject::StaticConfigName(),
(UClass::ClassConstructorType)InternalConstructor<UMyObject>,
(UClass::ClassVTableHelperCtorCallerType)InternalVTableHelperCtorCaller<UMyObject>,
&UMyObject::AddReferencedObjects, &UMyObject::Super::StaticClass,
&UMyObject::WithinClass::StaticClass);
}
return PrivateStaticClass;
};
static FCompiledInDefer Z_CompiledInDefer_UClass_UMyObject(Z_Construct_UClass_UMyObject, &UMyObject::StaticClass,
TEXT("/Script/MyProject"), TEXT("UMyObject"), false,
nullptr, nullptr, nullptr);
UMyObject::UMyObject(FVTableHelper& Helper) : Super(Helper)
{
};;
原始代码:
#include "CoreMinimal.h"
#include "MyObject.generated.h"
USTRUCT()
struct FMyStruct
{
GENERATED_BODY()
UPROPERTY()
int StructProperty;
};
展开GENERATED_BODY之后的代码:
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "UObject/ScriptMacros.h"
struct FMyStruct
{
friend struct Z_Construct_UScriptStruct_FMyStruct_Statics;
static class UScriptStruct* StaticStruct();;
int StructProperty;
};
.gen.cpp生成代码:
#include "UObject/GeneratedCppIncludes.h"
#include "MyProject/MyObject.h"
void EmptyLinkFunctionForGeneratedCodeMyObject()
{
}
// Cross Module References
THEMYPROJECT_API UScriptStruct* Z_Construct_UScriptStruct_FMyStruct();
UPackage* Z_Construct_UPackage__Script_MyProject();
// End Cross Module References
class UScriptStruct* FMyStruct::StaticStruct()
{
static class UScriptStruct* Singleton = NULL;
if (!Singleton)
{
extern THEMYPROJECT_API uint32 Get_Z_Construct_UScriptStruct_FMyStruct_CRC();
Singleton = GetStaticStruct(Z_Construct_UScriptStruct_FMyStruct, Z_Construct_UPackage__Script_MyProject(),
TEXT("MyStruct"), sizeof(FMyStruct), Get_Z_Construct_UScriptStruct_FMyStruct_CRC());
}
return Singleton;
}
static FCompiledInDeferStruct Z_CompiledInDeferStruct_UScriptStruct_FMyStruct(
FMyStruct::StaticStruct, TEXT("/Script/MyProject"), TEXT("MyStruct"), false, nullptr, nullptr);
static struct FScriptStruct_MyProject_StaticRegisterNativesFMyStruct
{
FScriptStruct_MyProject_StaticRegisterNativesFMyStruct()
{
UScriptStruct::DeferCppStructOps(FName(TEXT("MyStruct")), new UScriptStruct::TCppStructOps<FMyStruct>);
}
} ScriptStruct_MyProject_StaticRegisterNativesFMyStruct;
struct Z_Construct_UScriptStruct_FMyStruct_Statics
{
#if WITH_METADATA
static const UE4CodeGen_Private::FMetaDataPairParam Struct_MetaDataParams[];
#endif
static void* NewStructOps();
#if WITH_METADATA
static const UE4CodeGen_Private::FMetaDataPairParam NewProp_StructProperty_MetaData[];
#endif
static const UE4CodeGen_Private::FUnsizedIntPropertyParams NewProp_StructProperty;
static const UE4CodeGen_Private::FPropertyParamsBase* const PropPointers[];
static const UE4CodeGen_Private::FStructParams ReturnStructParams;
};
#if WITH_METADATA
const UE4CodeGen_Private::FMetaDataPairParam Z_Construct_UScriptStruct_FMyStruct_Statics::Struct_MetaDataParams[] = {
{"ModuleRelativePath", "MyObject.h"},
};
#endif
void* Z_Construct_UScriptStruct_FMyStruct_Statics::NewStructOps()
{
return (UScriptStruct::ICppStructOps*)new UScriptStruct::TCppStructOps<FMyStruct>();
}
#if WITH_METADATA
const UE4CodeGen_Private::FMetaDataPairParam Z_Construct_UScriptStruct_FMyStruct_Statics::
NewProp_StructProperty_MetaData[] = {
{"ModuleRelativePath", "MyObject.h"},
};
#endif
const UE4CodeGen_Private::FUnsizedIntPropertyParams Z_Construct_UScriptStruct_FMyStruct_Statics::NewProp_StructProperty
= {
UE4CodeGen_Private::EPropertyClass::Int, "StructProperty", RF_Public | RF_Transient | RF_MarkAsNative,
(EPropertyFlags)0x0010000000000000, 1, nullptr, STRUCT_OFFSET(FMyStruct, StructProperty), METADATA_PARAMS(
Z_Construct_UScriptStruct_FMyStruct_Statics::NewProp_StructProperty_MetaData,
ARRAY_COUNT(Z_Construct_UScriptStruct_FMyStruct_Statics::NewProp_StructProperty_MetaData))
};
const UE4CodeGen_Private::FPropertyParamsBase* const Z_Construct_UScriptStruct_FMyStruct_Statics::PropPointers[] = {
(const UE4CodeGen_Private::FPropertyParamsBase*)&Z_Construct_UScriptStruct_FMyStruct_Statics::
NewProp_StructProperty,
};
const UE4CodeGen_Private::FStructParams Z_Construct_UScriptStruct_FMyStruct_Statics::ReturnStructParams = {
(UObject* (*)())Z_Construct_UPackage__Script_MyProject,
nullptr,
&NewStructOps,
"MyStruct",
RF_Public | RF_Transient | RF_MarkAsNative,
EStructFlags(0x00000001),
sizeof(FMyStruct),
alignof(FMyStruct),
Z_Construct_UScriptStruct_FMyStruct_Statics::PropPointers,
ARRAY_COUNT(Z_Construct_UScriptStruct_FMyStruct_Statics::PropPointers),
METADATA_PARAMS(Z_Construct_UScriptStruct_FMyStruct_Statics::Struct_MetaDataParams,
ARRAY_COUNT(Z_Construct_UScriptStruct_FMyStruct_Statics::Struct_MetaDataParams))
};
UScriptStruct* Z_Construct_UScriptStruct_FMyStruct()
{
#if WITH_HOT_RELOAD
extern uint32 Get_Z_Construct_UScriptStruct_FMyStruct_CRC();
UPackage* Outer = Z_Construct_UPackage__Script_MyProject();
static UScriptStruct* ReturnStruct = FindExistingStructIfHotReloadOrDynamic(Outer, TEXT("MyStruct"), sizeof(FMyStruct), Get_Z_Construct_UScriptStruct_FMyStruct_CRC(), false);
#else
static UScriptStruct* ReturnStruct = nullptr;
#endif
if (!ReturnStruct)
{
UE4CodeGen_Private::ConstructUScriptStruct(ReturnStruct,
Z_Construct_UScriptStruct_FMyStruct_Statics::ReturnStructParams);
}
return ReturnStruct;
}
uint32 Get_Z_Construct_UScriptStruct_FMyStruct_CRC() { return 4118197761U; }
原始代码:
#include "CoreMinimal.h"
#include "Interface.h"
#include "MyObject.generated.h"
UINTERFACE()
class UMyInterface : public UInterface
{
GENERATED_BODY()
};
class IMyInterface
{
GENERATED_BODY()
public:
UFUNCTION()
virtual void InterfaceFunction();
};
展开GENERATED_BODY宏之后的代码:
#include "CoreMinimal.h"
#include "Interface.h"
#include "UObject/ObjectMacros.h"
#include "UObject/ScriptMacros.h"
class UMyInterface : public UInterface
{
private:
static void StaticRegisterNativesUMyInterface();
friend struct Z_Construct_UClass_UMyInterface_Statics;
public:
private:
UMyInterface& operator=(UMyInterface&&);
UMyInterface& operator=(const UMyInterface&);
static UClass* GetPrivateStaticClass();
public:
enum { StaticClassFlags=(CLASS_Abstract | CLASS_Interface | CLASS_Intrinsic) };
typedef UInterface Super;
typedef UMyInterface ThisClass;
inline static UClass* StaticClass() { return GetPrivateStaticClass(); }
inline static const TCHAR* StaticPackage() { return L"/Script/MyProject"; }
inline static EClassCastFlags StaticClassCastFlags() { return CASTCLASS_None; }
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);
}
inline void* operator new(const size_t InSize, EInternal* InMem) { return (void*)InMem; }
friend FArchive& operator<<(FArchive& Ar, UMyInterface*& Res) { return Ar << (UObject*&)Res; }
friend void operator<<(FStructuredArchive::FSlot InSlot, UMyInterface*& Res) { InSlot << (UObject*&)Res; }
UMyInterface(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()) : Super(ObjectInitializer)
{
};
private:
UMyInterface(UMyInterface&&);
UMyInterface(const UMyInterface&);
public:
UMyInterface(FVTableHelper& Helper);;
static UObject* __VTableCtorCaller(FVTableHelper& Helper) { return nullptr; };
static void __DefaultConstructor(const FObjectInitializer& X) { new((EInternal*)X.GetObj())UMyInterface(X); }
private:
__pragma (warning(pop));
};
class IMyInterface
{
__pragma (warning(push))
__pragma (warning(disable:4995))
__pragma (warning(disable:4996))
public:
static void execInterfaceFunction(UObject* Context, FFrame& Stack, void* const Z_Param__Result)
{
Stack.Code += !!Stack.Code;;
{
;;
((ThisClass*)(Context))->InterfaceFunction();
};
}
protected:
virtual ~IMyInterface()
{
}
public:
typedef UMyInterface UClassType;
typedef IMyInterface ThisClass;
virtual UObject* _getUObject() const
{
{
if ((!(0 && "Missing required implementation.")))
{
FDebug::LogAssertFailedMessage("0 && \"Missing required implementation.\"", "MyObject.h", 141, L"");
if (!FPlatformMisc::IsDebuggerPresent()) { FPlatformMisc::PromptForRemoteDebugging(false); }
((void)(FWindowsPlatformMisc::IsDebuggerPresent() && (__debugbreak(), 1)));;
FDebug::AssertFailed("0 && \"Missing required implementation.\"", "MyObject.h", 141);;
}
};
return nullptr;
}
private:
public:
virtual void InterfaceFunction();
};
.gen.cpp生成代码:
#include "UObject/GeneratedCppIncludes.h"
#include "MyProject/MyObject.h"
void EmptyLinkFunctionForGeneratedCodeMyObject()
{
}
// Cross Module References
UClass* Z_Construct_UClass_UMyInterface_NoRegister();
UClass* Z_Construct_UClass_UMyInterface();
UClass* Z_Construct_UClass_UInterface();
UPackage* Z_Construct_UPackage__Script_MyProject();
UFunction* Z_Construct_UFunction_UMyInterface_InterfaceFunction();
// End Cross Module References
void UMyInterface::StaticRegisterNativesUMyInterface()
{
UClass* Class = UMyInterface::StaticClass();
static const FNameNativePtrPair Funcs[] = {
{"InterfaceFunction", &IMyInterface::execInterfaceFunction},
};
FNativeFunctionRegistrar::RegisterFunctions(Class, Funcs, ARRAY_COUNT(Funcs));
}
struct Z_Construct_UFunction_UMyInterface_InterfaceFunction_Statics
{
#if WITH_METADATA
static const UE4CodeGen_Private::FMetaDataPairParam Function_MetaDataParams[];
#endif
static const UE4CodeGen_Private::FFunctionParams FuncParams;
};
#if WITH_METADATA
const UE4CodeGen_Private::FMetaDataPairParam Z_Construct_UFunction_UMyInterface_InterfaceFunction_Statics::
Function_MetaDataParams[] = {
{"ModuleRelativePath", "MyObject.h"},
};
#endif
const UE4CodeGen_Private::FFunctionParams Z_Construct_UFunction_UMyInterface_InterfaceFunction_Statics::FuncParams = {
(UObject*(*)())Z_Construct_UClass_UMyInterface, "InterfaceFunction", RF_Public | RF_Transient | RF_MarkAsNative,
nullptr, (EFunctionFlags)0x00020400, 0, nullptr, 0, 0, 0, METADATA_PARAMS(
Z_Construct_UFunction_UMyInterface_InterfaceFunction_Statics::Function_MetaDataParams,
ARRAY_COUNT(Z_Construct_UFunction_UMyInterface_InterfaceFunction_Statics::Function_MetaDataParams))
};
UFunction* Z_Construct_UFunction_UMyInterface_InterfaceFunction()
{
static UFunction* ReturnFunction = nullptr;
if (!ReturnFunction)
{
UE4CodeGen_Private::ConstructUFunction(ReturnFunction,
Z_Construct_UFunction_UMyInterface_InterfaceFunction_Statics::
FuncParams);
}
return ReturnFunction;
}
UClass* Z_Construct_UClass_UMyInterface_NoRegister()
{
return UMyInterface::StaticClass();
}
struct Z_Construct_UClass_UMyInterface_Statics
{
static UObject* (*const DependentSingletons[])();
static const FClassFunctionLinkInfo FuncInfo[];
#if WITH_METADATA
static const UE4CodeGen_Private::FMetaDataPairParam Class_MetaDataParams[];
#endif
static const FCppClassTypeInfoStatic StaticCppClassTypeInfo;
static const UE4CodeGen_Private::FClassParams ClassParams;
};
UObject* (*const Z_Construct_UClass_UMyInterface_Statics::DependentSingletons[])() = {
(UObject* (*)())Z_Construct_UClass_UInterface,
(UObject* (*)())Z_Construct_UPackage__Script_MyProject,
};
const FClassFunctionLinkInfo Z_Construct_UClass_UMyInterface_Statics::FuncInfo[] = {
{&Z_Construct_UFunction_UMyInterface_InterfaceFunction, "InterfaceFunction"}, // 156484113
};
#if WITH_METADATA
const UE4CodeGen_Private::FMetaDataPairParam Z_Construct_UClass_UMyInterface_Statics::Class_MetaDataParams[] = {
{"ModuleRelativePath", "MyObject.h"},
};
#endif
const FCppClassTypeInfoStatic Z_Construct_UClass_UMyInterface_Statics::StaticCppClassTypeInfo = {
TCppClassTypeTraits<IMyInterface>::IsAbstract,
};
const UE4CodeGen_Private::FClassParams Z_Construct_UClass_UMyInterface_Statics::ClassParams = {
&UMyInterface::StaticClass,
DependentSingletons, ARRAY_COUNT(DependentSingletons),
0x000040A1u,
FuncInfo, ARRAY_COUNT(FuncInfo),
nullptr, 0,
nullptr,
&StaticCppClassTypeInfo,
nullptr, 0,
METADATA_PARAMS(Z_Construct_UClass_UMyInterface_Statics::Class_MetaDataParams,
ARRAY_COUNT(Z_Construct_UClass_UMyInterface_Statics::Class_MetaDataParams))
};
UClass* Z_Construct_UClass_UMyInterface()
{
static UClass* OuterClass = nullptr;
if (!OuterClass)
{
UE4CodeGen_Private::ConstructUClass(OuterClass, Z_Construct_UClass_UMyInterface_Statics::ClassParams);
}
return OuterClass;
}
static TClassCompiledInDefer<UMyInterface>
AutoInitializeUMyInterface(L"UMyInterface", sizeof(UMyInterface), 3657494735);
UClass* UMyInterface::GetPrivateStaticClass()
{
static UClass* PrivateStaticClass = 0;
if (!PrivateStaticClass)
{
GetPrivateStaticClassBody(StaticPackage(),
(TCHAR*)L"UMyInterface" + 1 + ((StaticClassFlags & CLASS_Deprecated) ? 11 : 0),
PrivateStaticClass, StaticRegisterNativesUMyInterface, sizeof(UMyInterface),
(EClassFlags)UMyInterface::StaticClassFlags, UMyInterface::StaticClassCastFlags(),
UMyInterface::StaticConfigName(),
(UClass::ClassConstructorType)InternalConstructor<UMyInterface>,
(UClass::ClassVTableHelperCtorCallerType)InternalVTableHelperCtorCaller<UMyInterface>,
&UMyInterface::AddReferencedObjects, &UMyInterface::Super::StaticClass,
&UMyInterface::WithinClass::StaticClass);
}
return PrivateStaticClass;
};
static FCompiledInDefer Z_CompiledInDefer_UClass_UMyInterface(Z_Construct_UClass_UMyInterface,
&UMyInterface::StaticClass, TEXT("/Script/MyProject"),
TEXT("UMyInterface"), false, nullptr, nullptr, nullptr);
UMyInterface::UMyInterface(FVTableHelper& Helper) : Super(Helper)
{
};;
原始代码:
#include "CoreMinimal.h"
#include "MyObject.generated.h"
UENUM()
enum class EMyEnum
{
/** Comment 1 */
EnumValue1 = 1,
/** Comment 2 */
EnumValue2 = 2,
};
.gen.cpp生成代码:
#include "UObject/GeneratedCppIncludes.h"
#include "MyProject/MyObject.h"
void EmptyLinkFunctionForGeneratedCodeMyObject()
{
}
// Cross Module References
THEMYPROJECT_API UEnum* Z_Construct_UEnum_MyProject_EMyEnum();
UPackage* Z_Construct_UPackage__Script_MyProject();
// End Cross Module References
static UEnum* EMyEnum_StaticEnum()
{
static UEnum* Singleton = nullptr;
if (!Singleton)
{
Singleton = GetStaticEnum(Z_Construct_UEnum_MyProject_EMyEnum, Z_Construct_UPackage__Script_MyProject(),
TEXT("EMyEnum"));
}
return Singleton;
}
static FCompiledInDeferEnum Z_CompiledInDeferEnum_UEnum_EMyEnum(EMyEnum_StaticEnum, TEXT("/Script/MyProject"),
TEXT("EMyEnum"), false, nullptr, nullptr);
uint32 Get_Z_Construct_UEnum_MyProject_EMyEnum_CRC() { return 2698702339U; }
UEnum* Z_Construct_UEnum_MyProject_EMyEnum()
{
#if WITH_HOT_RELOAD
UPackage* Outer = Z_Construct_UPackage__Script_MyProject();
static UEnum* ReturnEnum = FindExistingEnumIfHotReloadOrDynamic(Outer, TEXT("EMyEnum"), 0, Get_Z_Construct_UEnum_MyProject_EMyEnum_CRC(), false);
#else
static UEnum* ReturnEnum = nullptr;
#endif // WITH_HOT_RELOAD
if (!ReturnEnum)
{
static const UE4CodeGen_Private::FEnumeratorParam Enumerators[] = {
{"EMyEnum::EnumValue1", (int64)EMyEnum::EnumValue1},
{"EMyEnum::EnumValue2", (int64)EMyEnum::EnumValue2},
};
#if WITH_METADATA
const UE4CodeGen_Private::FMetaDataPairParam Enum_MetaDataParams[] = {
{"EnumValue1.ToolTip", "Comment 1"},
{"EnumValue2.ToolTip", "Comment 2"},
{"ModuleRelativePath", "MyObject.h"},
};
#endif
static const UE4CodeGen_Private::FEnumParams EnumParams = {
(UObject*(*)())Z_Construct_UPackage__Script_MyProject,
UE4CodeGen_Private::EDynamicType::NotDynamic,
"EMyEnum",
RF_Public | RF_Transient | RF_MarkAsNative,
nullptr,
(uint8)UEnum::ECppForm::EnumClass,
"EMyEnum",
Enumerators,
ARRAY_COUNT(Enumerators),
METADATA_PARAMS(Enum_MetaDataParams, ARRAY_COUNT(Enum_MetaDataParams))
};
UE4CodeGen_Private::ConstructUEnum(ReturnEnum, EnumParams);
}
return ReturnEnum;
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。