StaticClass 和 GetClass 的区别 StaticClass
是继承自 UObject 类的 static 函数,GetClass
是 UObjectBase
的成员函数。
UObjectBase
的 GetClass
获取到的 UClass 就是在 NewObject 时传递进来的 UClass.(代码在 UObject\UObjectGlobal.cpp
中)
用途不一样,StaticClass
是在获取具体类型的 UClass,而 GetClass
是获取到当前对象的真实 UClass。
StaticClass 是如何定义的 在 UE 中可以对 UObject 的类执行 UXXX::StaticClass
方法来获取到它的 UClass 对象。
但是它是如何定义的?首先要看我们声明对象的 MyActor.generated.h
中(以 AMyActor 类为例):
1 template <> MICROEND_423_API UClass* StaticClass<class AMyActor > ();
为 AMyActor 类特化了 StaticClass
的版本。再去 MyActor.gen.cpp
中找以下它的实现:
1 2 3 4 5 IMPLEMENT_CLASS (AMyActor, 31943282 );template <> MICROEND_423_API UClass* StaticClass<AMyActor>(){ return AMyActor::StaticClass (); }
从这里看也就只是转发调用而已,但是关键点隐藏在其他地方。 首先 AMyActor::StaticClass
类的定义是在 AMyActor.generated.h
的DECLARE_CLASS
宏中(该宏定义在 ObjectMacros.h#L1524 ),返回的是GetPrivateStaticClass
的调用。
而 GetPrivateStaticClass
则在 AMyAcotr.gen.cpp
中的 IMPLEMENT_CLASS 实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #define IMPLEMENT_CLASS(TClass, TClassCrc) \ static TClassCompiledInDefer<TClass> AutoInitialize###TClass(TEXT(#TClass), sizeof(TClass), TClassCrc); \ UClass* TClass::GetPrivateStaticClass() \ { \ static UClass* PrivateStaticClass = NULL; \ if (!PrivateStaticClass) \ { \ \ GetPrivateStaticClassBody(\ StaticPackage(), \ (TCHAR*)TEXT(#TClass) + 1 + ((StaticClassFlags & CLASS_Deprecated) ? 11 : 0), \ PrivateStaticClass, \ StaticRegisterNatives###TClass, \ sizeof(TClass), \ alignof(TClass), \ (EClassFlags)TClass::StaticClassFlags, \ TClass::StaticClassCastFlags(), \ TClass::StaticConfigName(), \ (UClass::ClassConstructorType)InternalConstructor<TClass> , \ (UClass::ClassVTableHelperCtorCallerType)InternalVTableHelperCtorCaller<TClass> , \ &TClass::AddReferencedObjects, \ &TClass::Super::StaticClass, \ &TClass::WithinClass::StaticClass \ ); \ } \ return PrivateStaticClass; \ }
可以看到 GetPrivateStaticClass
其实就是通过这些元数据构造出 UClass 的。
如下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 IMPLEMENT_CLASS (AMyActor, 3240835608 );static TClassCompiledInDefer < AMyActor > AutoInitializeAMyActor (TEXT ("AMyActor" ), sizeof (AMyActor), 3240835608 );UClass * AMyActor::GetPrivateStaticClass () { static UClass * PrivateStaticClass = NULL ; if (!PrivateStaticClass) { GetPrivateStaticClassBody ( StaticPackage (), (TCHAR*)TEXT ("AMyActor" ) + 1 + ((StaticClassFlags & CLASS_Deprecated) ? 11 : 0 ), PrivateStaticClass, StaticRegisterNativesAMyActor, sizeof (AMyActor), alignof (AMyActor), (EClassFlags) AMyActor::StaticClassFlags, AMyActor::StaticClassCastFlags (), AMyActor::StaticConfigName (), (UClass::ClassConstructorType) InternalConstructor<AMyActor>, (UClass::ClassVTableHelperCtorCallerType) InternalVTableHelperCtorCaller<AMyActor>, &AMyActor::AddReferencedObjects, &AMyActor::Super::StaticClass, &AMyActor::WithinClass::StaticClass ); } return PrivateStaticClass; };
UClass 中的函数指针 上面代码中比较关键的点为:
1 2 (UClass::ClassConstructorType)InternalConstructor<TClass>, \ (UClass::ClassVTableHelperCtorCallerType)InternalVTableHelperCtorCaller<TClass>, \
这两行是模板实例化出了两个函数并转换成函数指针传递给GetPrivateStaticClassBody
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 template <class T>void InternalConstructor (const FObjectInitializer& X ) { T::__DefaultConstructor(X); } template <class T>UObject* InternalVTableHelperCtorCaller (FVTableHelper& Helper) { return T::__VTableCtorCaller(Helper); }
就是对 __DefaultConstructor
这样函数的的转发调用。
UClass::ClassConstructorType
与 UClass::ClassVTableHelperCtorCallerType
这两个 typedef
为:
1 2 typedef void (*ClassConstructorType) (const FObjectInitializer&) ;typedef UObject* (*ClassVTableHelperCtorCallerType) (FVTableHelper& Helper);
GetPrivateStaticClassBody 其中的 GetPrivateStaticClassBody
函数是定义在 Runtime\CoreUObject\Private\UObject\Class.cpp 中的。
原型为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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, UClass::ClassAddReferencedObjectsType InClassAddReferencedObjects, UClass::StaticClassFunctionType InSuperClassFn, UClass::StaticClassFunctionType InWithinClassFn, bool bIsDynamic ) ;
其中第四个参数是传入注册 Native 函数的函数指针,该函数在 MyActor.gen.cpp
中生成,也可以通过在 UFUNCTION 中添加 CustomThunk
函数来自己实现,UnLua 的覆写 C++ 函数就是基于替换 thunk 函数做的。
GetPrivateStaticClassBody
中通过 (UClass*)GUObjectAllocator.AllocateUObject
来分配出 UClass 的内存,因为所有的 UClass 结构都一致。
1 2 3 4 5 6 7 8 9 10 void AMyActor::StaticRegisterNativesAMyActor () { UClass* Class = AMyActor::StaticClass (); static const FNameNativePtrPair Funcs[] = { { "ReceiveBytes" , &AMyActor::execReceiveBytes }, { "TESTFUNC" , &AMyActor::execTESTFUNC }, }; FNativeFunctionRegistrar::RegisterFunctions (Class, Funcs, ARRAY_COUNT (Funcs)); }
其实就是把 Native 的函数通过 AddNativeFunction
添加到 UClass 中:
1 2 3 4 5 6 7 8 void FNativeFunctionRegistrar::RegisterFunctions (class UClass* Class, const FNameNativePtrPair* InArray, int32 NumFunctions) { for (; NumFunctions; ++InArray, --NumFunctions) { Class->AddNativeFunction (UTF8_TO_TCHAR (InArray->NameUTF8), InArray->Pointer); } }