反射系统的代码展开
我们创建一个actor
build后生成.gen.h和.gen.cpp
然后去拿gen.h和gen.cpp
TestPlugin\Intermediate\Build\Win64\UE4Editor\Inc\TestPlugin
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class TESTPLUGIN_API AMyActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMyActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
我们对这个文件的宏做展开
GENERATED_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);
这个GENERATED_BODY 根据一系列宏展开成
TestPlugin_Source_TestPlugin_Public_MyActor_h_12_GENERATED_BODY
写在了gen.h里面
#define TestPlugin_Source_TestPlugin_Public_MyActor_h_12_GENERATED_BODY \
PRAGMA_DISABLE_DEPRECATION_WARNINGS \
public: \
TestPlugin_Source_TestPlugin_Public_MyActor_h_12_PRIVATE_PROPERTY_OFFSET \
TestPlugin_Source_TestPlugin_Public_MyActor_h_12_SPARSE_DATA \
TestPlugin_Source_TestPlugin_Public_MyActor_h_12_RPC_WRAPPERS_NO_PURE_DECLS \
TestPlugin_Source_TestPlugin_Public_MyActor_h_12_INCLASS_NO_PURE_DECLS \
TestPlugin_Source_TestPlugin_Public_MyActor_h_12_ENHANCED_CONSTRUCTORS \
private: \
PRAGMA_ENABLE_DEPRECATION_WARNINGS
我们手动对这些宏进行展开,是这样的
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class TESTPLUGIN_API AMyActor : public AActor
{
private:
static void StaticRegisterNativesAMyActor();
friend struct Z_Construct_UClass_AMyActor_Statics;
public:
DECLARE_CLASS(AMyActor, AActor, COMPILED_IN_FLAGS(0 | CLASS_Config), CASTCLASS_None, TEXT("/Script/TestPlugin"), NO_API) \
DECLARE_SERIALIZER(AMyActor)
private:
/** Private move- and copy-constructors, should never be used */
NO_API AMyActor(AMyActor&&);
NO_API AMyActor(const AMyActor&);
public:
DECLARE_VTABLE_PTR_HELPER_CTOR(NO_API, AMyActor);
DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER(AMyActor);
DEFINE_DEFAULT_CONSTRUCTOR_CALL(AMyActor)
public:
// Sets default values for this actor's properties
AMyActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
我们展开
DECLARE_CLASS
DECLARE_SERIALIZER
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class TESTPLUGIN_API AMyActor : public AActor
{
private:
static void StaticRegisterNativesAMyActor();
friend struct Z_Construct_UClass_AMyActor_Statics;
public:
private:
AMyActor& operator=(AMyActor&&);
AMyActor& operator=(const AMyActor&);
NO_API static UClass* GetPrivateStaticClass();
public:
/** Bitwise union of #EClassFlags pertaining to this class.*/
enum { StaticClassFlags=COMPILED_IN_FLAGS(0 | CLASS_Config) };
/** Typedef for the base class ({{ typedef-type }}) */
typedef AActor Super;
/** Typedef for {{ typedef-type }}. */
typedef AMyActor 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 TEXT("/Script/TestPlugin");
}
/** Returns the static cast flags for this class */
inline static EClassCastFlags StaticClassCastFlags()
{
return CASTCLASS_None;
}
/** 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;
}
friend FArchive& operator<<(FArchive& Ar, AMyActor*& Res)
{
return Ar << (UObject*&)Res;
}
friend void operator<<(FStructuredArchive::FSlot InSlot, AMyActor*& Res)
{
InSlot << (UObject*&)Res;
}
private:
/** Private move- and copy-constructors, should never be used */
NO_API AMyActor(AMyActor&&);
NO_API AMyActor(const AMyActor&);
public:
DECLARE_VTABLE_PTR_HELPER_CTOR(NO_API, AMyActor);
DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER(AMyActor);
DEFINE_DEFAULT_CONSTRUCTOR_CALL(AMyActor)
public:
// Sets default values for this actor's properties
AMyActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
我们到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 "TestPlugin/Public/MyActor.h"
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable : 4883)
#endif
PRAGMA_DISABLE_DEPRECATION_WARNINGS
void EmptyLinkFunctionForGeneratedCodeMyActor() {}
// Cross Module References
TESTPLUGIN_API UClass* Z_Construct_UClass_AMyActor_NoRegister();
TESTPLUGIN_API UClass* Z_Construct_UClass_AMyActor();
ENGINE_API UClass* Z_Construct_UClass_AActor();
UPackage* Z_Construct_UPackage__Script_TestPlugin();
// End Cross Module References
void AMyActor::StaticRegisterNativesAMyActor()
{
}
UClass* Z_Construct_UClass_AMyActor_NoRegister()
{
return AMyActor::StaticClass();
}
struct Z_Construct_UClass_AMyActor_Statics
{
static UObject* (*const DependentSingletons[])();
#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_AMyActor_Statics::DependentSingletons[])() = {
(UObject* (*)())Z_Construct_UClass_AActor,
(UObject* (*)())Z_Construct_UPackage__Script_TestPlugin,
};
#if WITH_METADATA
const UE4CodeGen_Private::FMetaDataPairParam Z_Construct_UClass_AMyActor_Statics::Class_MetaDataParams[] = {
{ "IncludePath", "MyActor.h" },
{ "ModuleRelativePath", "Public/MyActor.h" },
};
#endif
const FCppClassTypeInfoStatic Z_Construct_UClass_AMyActor_Statics::StaticCppClassTypeInfo = {
TCppClassTypeTraits<AMyActor>::IsAbstract,
};
const UE4CodeGen_Private::FClassParams Z_Construct_UClass_AMyActor_Statics::ClassParams = {
&AMyActor::StaticClass,
"Engine",
&StaticCppClassTypeInfo,
DependentSingletons,
nullptr,
nullptr,
nullptr,
UE_ARRAY_COUNT(DependentSingletons),
0,
0,
0,
0x009000A4u,
METADATA_PARAMS(Z_Construct_UClass_AMyActor_Statics::Class_MetaDataParams, UE_ARRAY_COUNT(Z_Construct_UClass_AMyActor_Statics::Class_MetaDataParams))
};
UClass* Z_Construct_UClass_AMyActor()
{
static UClass* OuterClass = nullptr;
if (!OuterClass)
{
UE4CodeGen_Private::ConstructUClass(OuterClass, Z_Construct_UClass_AMyActor_Statics::ClassParams);
}
return OuterClass;
}
IMPLEMENT_CLASS(AMyActor, 3854597253);
template<> TESTPLUGIN_API UClass* StaticClass<AMyActor>()
{
return AMyActor::StaticClass();
}
static FCompiledInDefer Z_CompiledInDefer_UClass_AMyActor(Z_Construct_UClass_AMyActor, &AMyActor::StaticClass, TEXT("/Script/TestPlugin"), TEXT("AMyActor"), false, nullptr, nullptr, nullptr);
DEFINE_VTABLE_PTR_HELPER_CTOR(AMyActor);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
#ifdef _MSC_VER
#pragma warning (pop)
#endif
我们要展开这个东西
IMPLEMENT_CLASS(AMyActor, 3854597253);
// IMPLEMENT_CLASS(AMyActor, 3854597253);
// #define IMPLEMENT_CLASS(AMyActor, 3854597253)
static TClassCompiledInDefer<AMyActor> AutoInitializeAMyActor(TEXT("AMyActor"), sizeof(AMyActor), 3854597253);
UClass* AMyActor::GetPrivateStaticClass()
{
static UClass* PrivateStaticClass = NULL;
if (!PrivateStaticClass)
{
/* this could be handled with templates, but we want it external to avoid code bloat */
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;
}
我们发现之前.h的 StaticClass()就是return这个。
展开
DEFINE_VTABLE_PTR_HELPER_CTOR(AMyActor);
用于热更新
// DEFINE_VTABLE_PTR_HELPER_CTOR(AMyActor);
// #define DEFINE_VTABLE_PTR_HELPER_CTOR(TClass) \
AMyActor::AMyActor(FVTableHelper& Helper) : Super(Helper) {};
我们开始加几个个函数在编译
UPROPERTY()
UBoxComponent* MyBox1;
UPROPERTY(EditDefaultsOnly, Category = "Box")
UBoxComponent* MyBox2;
UFUNCTION(BlueprintCallable, Category = "TestFunc")
void TestFunc1();
UFUNCTION(BlueprintCallable, Category = "TestFunc")
bool TestFunc2();
UFUNCTION(BlueprintCallable, Category = "TestFunc")
FString TestFunc3(int32 InValue, const FString& Name, bool bShow);
UFUNCTION()
void TestFunc4();
UFUNCTION(BlueprintNativeEvent)
void TestFunc5(int32 IntValue);
然后发现我们的宏有新的值了 gen.h和gen.cpp
#define TestPlugin_Source_TestPlugin_Public_MyActor_h_12_SPARSE_DATA
#define TestPlugin_Source_TestPlugin_Public_MyActor_h_12_RPC_WRAPPERS \
virtual void TestFunc5_Implementation(int32 IntValue); \
\
DECLARE_FUNCTION(execTestFunc5); \
DECLARE_FUNCTION(execTestFunc4); \
DECLARE_FUNCTION(execTestFunc3); \
DECLARE_FUNCTION(execTestFunc2); \
DECLARE_FUNCTION(execTestFunc1);
DEFINE_FUNCTION(AMyActor::execTestFunc5)
{
P_GET_PROPERTY(FIntProperty,Z_Param_IntValue);
P_FINISH;
P_NATIVE_BEGIN;
P_THIS->TestFunc5_Implementation(Z_Param_IntValue);
P_NATIVE_END;
}
DEFINE_FUNCTION(AMyActor::execTestFunc4)
{
P_FINISH;
P_NATIVE_BEGIN;
P_THIS->TestFunc4();
P_NATIVE_END;
}
DEFINE_FUNCTION(AMyActor::execTestFunc3)
{
P_GET_PROPERTY(FIntProperty,Z_Param_InValue);
P_GET_PROPERTY(FStrProperty,Z_Param_Name);
P_GET_UBOOL(Z_Param_bShow);
P_FINISH;
P_NATIVE_BEGIN;
*(FString*)Z_Param__Result=P_THIS->TestFunc3(Z_Param_InValue,Z_Param_Name,Z_Param_bShow);
P_NATIVE_END;
}
DEFINE_FUNCTION(AMyActor::execTestFunc2)
{
P_FINISH;
P_NATIVE_BEGIN;
*(bool*)Z_Param__Result=P_THIS->TestFunc2();
P_NATIVE_END;
}
DEFINE_FUNCTION(AMyActor::execTestFunc1)
{
P_FINISH;
P_NATIVE_BEGIN;
P_THIS->TestFunc1();
P_NATIVE_END;
}
static FName NAME_AMyActor_TestFunc5 = FName(TEXT("TestFunc5"));
void AMyActor::TestFunc5(int32 IntValue)
{
MyActor_eventTestFunc5_Parms Parms;
Parms.IntValue=IntValue;
ProcessEvent(FindFunctionChecked(NAME_AMyActor_TestFunc5),&Parms);
}
void AMyActor::StaticRegisterNativesAMyActor()
{
UClass* Class = AMyActor::StaticClass();
static const FNameNativePtrPair Funcs[] = {
{ "TestFunc1", &AMyActor::execTestFunc1 },
{ "TestFunc2", &AMyActor::execTestFunc2 },
{ "TestFunc3", &AMyActor::execTestFunc3 },
{ "TestFunc4", &AMyActor::execTestFunc4 },
{ "TestFunc5", &AMyActor::execTestFunc5 },
};
FNativeFunctionRegistrar::RegisterFunctions(Class, Funcs, UE_ARRAY_COUNT(Funcs));
}
属性方面生成的代码
#if WITH_METADATA
const UE4CodeGen_Private::FMetaDataPairParam Z_Construct_UClass_AMyActor_Statics::NewProp_MyBox1_MetaData[] = {
{ "EditInline", "true" },
{ "ModuleRelativePath", "Public/MyActor.h" },
};
#endif
const UE4CodeGen_Private::FObjectPropertyParams Z_Construct_UClass_AMyActor_Statics::NewProp_MyBox1 = { "MyBox1", nullptr, (EPropertyFlags)0x0010000000080008, UE4CodeGen_Private::EPropertyGenFlags::Object, RF_Public|RF_Transient|RF_MarkAsNative, 1, STRUCT_OFFSET(AMyActor, MyBox1), Z_Construct_UClass_UBoxComponent_NoRegister, METADATA_PARAMS(Z_Construct_UClass_AMyActor_Statics::NewProp_MyBox1_MetaData, UE_ARRAY_COUNT(Z_Construct_UClass_AMyActor_Statics::NewProp_MyBox1_MetaData)) };
#if WITH_METADATA
const UE4CodeGen_Private::FMetaDataPairParam Z_Construct_UClass_AMyActor_Statics::NewProp_MyBox2_MetaData[] = {
{ "Category", "Box" },
{ "EditInline", "true" },
{ "ModuleRelativePath", "Public/MyActor.h" },
};
#endif
const UE4CodeGen_Private::FObjectPropertyParams Z_Construct_UClass_AMyActor_Statics::NewProp_MyBox2 = { "MyBox2", nullptr, (EPropertyFlags)0x0010000000090009, UE4CodeGen_Private::EPropertyGenFlags::Object, RF_Public|RF_Transient|RF_MarkAsNative, 1, STRUCT_OFFSET(AMyActor, MyBox2), Z_Construct_UClass_UBoxComponent_NoRegister, METADATA_PARAMS(Z_Construct_UClass_AMyActor_Statics::NewProp_MyBox2_MetaData, UE_ARRAY_COUNT(Z_Construct_UClass_AMyActor_Statics::NewProp_MyBox2_MetaData)) };
const UE4CodeGen_Private::FPropertyParamsBase* const Z_Construct_UClass_AMyActor_Statics::PropPointers[] = {
(const UE4CodeGen_Private::FPropertyParamsBase*)&Z_Construct_UClass_AMyActor_Statics::NewProp_MyBox1,
(const UE4CodeGen_Private::FPropertyParamsBase*)&Z_Construct_UClass_AMyActor_Statics::NewProp_MyBox2,
};
我们把那几个函数宏定义展开
void AMyActor::execTestFunc5(UObject* Context, FFrame& Stack, void* const Z_Param__Result)
{
FIntProperty::TCppType Z_Param_IntValue = FIntProperty::GetDefaultPropertyValue();
Stack.StepCompiledIn<FIntProperty>(&Z_Param_IntValue);
Stack.Code += !!Stack.Code;
{
FBlueprintEventTimer::FScopedNativeTimer ScopedNativeCallTimer;
P_THIS->TestFunc5_Implementation(Z_Param_IntValue);
};
}
void AMyActor::execTestFunc4(UObject* Context, FFrame& Stack, void* const Z_Param__Result)
{
Stack.Code += !!Stack.Code;
{
FBlueprintEventTimer::FScopedNativeTimer ScopedNativeCallTimer;
P_THIS->TestFunc4();
};
}
void AMyActor::execTestFunc3(UObject* Context, FFrame& Stack, void* const Z_Param__Result)
{
FIntProperty::TCppType Z_Param_IntValue = FIntProperty::GetDefaultPropertyValue();
Stack.StepCompiledIn<FIntProperty>(&Z_Param_IntValue);
FStrProperty::TCppType Z_Param_Name = FStrProperty::GetDefaultPropertyValue();
Stack.StepCompiledIn<FStrProperty>(&Z_Param_Name);
P_GET_UBOOL(Z_Param_bShow);
Stack.Code += !!Stack.Code;
{
FBlueprintEventTimer::FScopedNativeTimer ScopedNativeCallTimer;
*(FString*)Z_Param__Result = P_THIS->TestFunc3(Z_Param_InValue, Z_Param_Name, Z_Param_bShow);
}
}
void AMyActor::execTestFunc2(UObject* Context, FFrame& Stack, void* const Z_Param__Result)
{
Stack.Code += !!Stack.Code;
{
FBlueprintEventTimer::FScopedNativeTimer ScopedNativeCallTimer;
*(bool*)Z_Param__Result = P_THIS->TestFunc2();
};
}
void AMyActor::execTestFunc1(UObject* Context, FFrame& Stack, void* const Z_Param__Result)
{
Stack.Code += !!Stack.Code;
{
FBlueprintEventTimer::FScopedNativeTimer ScopedNativeCallTimer;
P_THIS->TestFunc1();
};
}
我们能够看到参数的处理和调用。添加UFUNCTION注解的函数最终会被生成这样。
UE 蓝图虚拟机
- FFrame 虚拟机执行系统
- FKismetCompilerContex 编译器
- UStruct::Script 字节码数组
- CNative exec##函数名 函数
- 临时堆栈
我们看下这个类,包含执行数据的上下文
struct FFrame : public FOutputDevice
{
public:
// Variables.
UFunction* Node; // 蓝图节点
UObject* Object; // 所属对象
uint8* Code; // 字节码数组
uint8* Locals; // 局部变量
FProperty* MostRecentProperty;
uint8* MostRecentPropertyAddress;
/** The execution flow stack for compiled Kismet code */
FlowStackType FlowStack;
/** Previous frame on the stack */
FFrame* PreviousFrame;
/** contains information on any out parameters */
FOutParmRec* OutParms;
/** If a class is compiled in then this is set to the property chain for compiled-in functions. In that case, we follow the links to setup the args instead of executing by code. */
FField* PropertyChainForCompiledIn;
/** Currently executed native function */
UFunction* CurrentNativeFunction; // exec##函数
bool bArrayContextFailed;
// 各种read
template<typename TNumericType>
TNumericType ReadInt();
float ReadFloat();
FName ReadName();
UObject* ReadObject();
int32 ReadWord();
FProperty* ReadProperty();
然后我们就可以回头看函数的执行了
void AMyActor::execTestFunc5(UObject* Context, FFrame& Stack, void* const Z_Param__Result)
{
FIntProperty::TCppType Z_Param_IntValue = FIntProperty::GetDefaultPropertyValue();
Stack.StepCompiledIn<FIntProperty>(&Z_Param_IntValue);
Stack.Code += !!Stack.Code;
{
FBlueprintEventTimer::FScopedNativeTimer ScopedNativeCallTimer;
P_THIS->TestFunc5_Implementation(Z_Param_IntValue);
};
}
可以具体看一下Stack.StepCompiledIn这个取参数的过程
然后后面直接执行
蓝图的注册
我们看这里
void AMyActor::StaticRegisterNativesAMyActor()
{
UClass* Class = AMyActor::StaticClass();
static const FNameNativePtrPair Funcs[] = {
{ "TestFunc1", &AMyActor::execTestFunc1 },
{ "TestFunc2", &AMyActor::execTestFunc2 },
{ "TestFunc3", &AMyActor::execTestFunc3 },
{ "TestFunc4", &AMyActor::execTestFunc4 },
{ "TestFunc5", &AMyActor::execTestFunc5 },
};
FNativeFunctionRegistrar::RegisterFunctions(Class, Funcs, UE_ARRAY_COUNT(Funcs));
}
这里会把函数注册到类里面
void FNativeFunctionRegistrar::RegisterFunctions(class UClass* Class, const FNameNativePtrPair* InArray, int32 NumFunctions)
{
for (; NumFunctions; ++InArray, --NumFunctions)
{
Class->AddNativeFunction(UTF8_TO_TCHAR(InArray->NameUTF8), InArray->Pointer);
}
}
里面一个是放到热加载的map里面,一个是放到class的类里面
struct Z_Construct_UFunction_AMyActor_TestFunc1_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_AMyActor_TestFunc1_Statics::Function_MetaDataParams[] = {
{ "Category", "TestFunc" },
{ "ModuleRelativePath", "Public/MyActor.h" },
};
#endif
const UE4CodeGen_Private::FFunctionParams Z_Construct_UFunction_AMyActor_TestFunc1_Statics::FuncParams = { (UObject*(*)())Z_Construct_UClass_AMyActor, nullptr, "TestFunc1", nullptr, nullptr, 0, nullptr, 0, RF_Public|RF_Transient|RF_MarkAsNative, (EFunctionFlags)0x04020401, 0, 0, METADATA_PARAMS(Z_Construct_UFunction_AMyActor_TestFunc1_Statics::Function_MetaDataParams, UE_ARRAY_COUNT(Z_Construct_UFunction_AMyActor_TestFunc1_Statics::Function_MetaDataParams)) };
UFunction* Z_Construct_UFunction_AMyActor_TestFunc1()
{
static UFunction* ReturnFunction = nullptr;
if (!ReturnFunction)
{
UE4CodeGen_Private::ConstructUFunction(ReturnFunction, Z_Construct_UFunction_AMyActor_TestFunc1_Statics::FuncParams);
}
return ReturnFunction;
}
这里包含了该函数的元数据和函数UFUNCTION的构造
顺着这个函数可以看UFunction是如何构造的。
void ConstructUFunction(UFunction*& OutFunction, const FFunctionParams& Params)
ProcessEvent
static FName NAME_AMyActor_TestFunc5 = FName(TEXT("TestFunc5"));
void AMyActor::TestFunc5(int32 IntValue)
{
MyActor_eventTestFunc5_Parms Parms;
Parms.IntValue=IntValue;
ProcessEvent(FindFunctionChecked(NAME_AMyActor_TestFunc5),&Parms);
}
这里面是一个通过反射找函数对象的过程,然后给ProcessEvent执行
UFunction* UObject::FindFunctionChecked( FName InName ) const
{
UFunction* Result = FindFunction(InName);
if (Result == NULL)
{
UE_LOG(LogScriptCore, Fatal, TEXT("Failed to find function %s in %s"), *InName.ToString(), *GetFullName());
}
return Result;
}
virtual void ProcessEvent( UFunction* Function, void* Parms );
一路找进去能找到执行的地方
Function->Invoke(this, NewStack, ReturnValueAddress);
void UFunction::Invoke(UObject* Obj, FFrame& Stack, RESULT_DECL)
{
checkSlow(Func);
UClass* OuterClass = (UClass*)GetOuter();
if (OuterClass->IsChildOf(UInterface::StaticClass()))
{
Obj = (UObject*)Obj->GetInterfaceAddress(OuterClass);
}
TGuardValue<UFunction*> NativeFuncGuard(Stack.CurrentNativeFunction, this);
return (*Func)(Obj, Stack, RESULT_PARAM);
}
然后在这里执行例如上面 的 exec函数