UE4反射机制的通俗理解【生成第一个UClass】

上一篇我们讲到了利用static变量把构造函数指针以及生成的类信息都收集到了全局静态数组中。这一篇就要讲讲,收集好了之后,我们是怎么利用这些收集的信息来生成我们的UClass的。

上一篇最后说到了,IMPLEMENT_VM_FUNCTION(EX_CallMath, execCallMathFunction)会触发UObject::StaticClass()的调用,这里会生成第一个UClass*。

那么UObject的IMPLEMENT_CLASS是在哪里定义的呢?就在NoexportTypes.h文件中。

这个文件定义了Eunm,Struct和UObject,但是不参与编译,只是提供给UHT来生成反射信息的相关代码以便于其他地方去调用。那我们接下来去看下StaticClass具体做了什么。

//类的声明值
DECLARE_CLASS(UMyClass, UObject, COMPILED_IN_FLAGS(0), CASTCLASS_None, TEXT("/Script/Hello"), NO_API)
//值的传递
UClass* UMyClass::GetPrivateStaticClass(const TCHAR* Package)
{
    static UClass* PrivateStaticClass = NULL;   //静态变量,下回访问就不用再去查找了
    if (!PrivateStaticClass)
    {
        /* this could be handled with templates, but we want it external to avoid code bloat */
        GetPrivateStaticClassBody(
            Package,    //包名,TEXT("/Script/Hello"),用来把本UClass*构造在该UPackage里
            (TCHAR*)TEXT("UMyClass") + 1 + ((StaticClassFlags & CLASS_Deprecated) ? 11 : 0),//类名,+1去掉U、A、F前缀,+11去掉Deprecated_前缀
            PrivateStaticClass, //输出引用,所以值会被改变
            StaticRegisterNativesUMyClass,  //注册类Native函数的指针
            sizeof(UMyClass),   //类大小
            UMyClass::StaticClassFlags, //类标记,值为CLASS_Intrinsic,表示在C++代码里定义的类
            UMyClass::StaticClassCastFlags(),   //虽然是调用,但只是简单返回值CASTCLASS_None
            UMyClass::StaticConfigName(),   //配置文件名,用于从config里读取值
            (UClass::ClassConstructorType)InternalConstructor<UMyClass>,//构造函数指针,包了一层
            (UClass::ClassVTableHelperCtorCallerType)InternalVTableHelperCtorCaller<UMyClass>,//hotreload的时候使用来构造虚函数表,暂时不管
            &UMyClass::AddReferencedObjects,   //GC使用的添加额外引用对象的静态函数指针,若没有定义,则会调用到UObject::AddReferencedObjects,默认函数体为空。
            &UMyClass::Super::StaticClass,  //获取基类UClass*的函数指针,这里Super是UObject
            &UMyClass::WithinClass::StaticClass //获取对象外部类UClass*的函数指针,默认是UObject
        );
    }
    return PrivateStaticClass;
}

里面基本上就是简单的传值给GetPrivateStaticClassBody。

  1. Package名字的传入是为了在构建UClass*之后,把UClass*对象的OuterPrivate设定为正确的UPackage*对象。在UE里,UObject必须属于某个UPackage。所以传入名字是为了后续查找或者创建出前置需要的UPackage对象。“/Script/”开头表示这是个代码模块。
  2. StaticRegisterNativesUMyClass这个函数的名字是用宏拼接的,分别在.generated.h和.gen.cpp里声明和定义。
  3. InternalConstructor<UMyClass>这个模板函数是为了包一下C++的构造函数,因为你没法直接去获得C++构造函数的函数指针。在.generated.h里会根据情况生成这两个宏的调用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值