UE 反射系统的代码展开

反射系统的代码展开

我们创建一个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函数

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇