DEV

CPP反射分析和实现

本文不讨论代码预分析头文件生成反射信息的过程,在确定了runtime时传入的反射信息的结构后,很容易利用像libClang或者纯手写的简易语法分析,来处理源代码并生成文件。 本文着重于Runtime阶段反射信息的构建,第一部分简单分析UE反射系统的实现,第二部分简述一个自定义运行时反射系统的实现

当前版本比较潦草,仅仅为了记录,后续会陆续修改

一. UE的反射实现浅析

首先从全局上来思考一个runtime反射系统,我们需要获取反射的信息,这包括需要反射的类,类中需要反射的成员函数和成员变量,这些反射信息是是一组特殊的结构体,包含了对这些反射对象的详细描述。

其次我们需要有一个对象来保存上述的


1.反射生成代码注册信息调用

各个CPP文件的反射信息都是在编译器Preprocessor阶段分析头文件生成的,核心就是在生成文件中直接写入附加的发射信息,略过各个反射类型的结构定义,以及各种其他方法的生成(RPC,序列化),排除那些大量的宏定义 最核心的结构体就是FRegisterCompiledInInfo
例如下面的一个例子

static FRegisterCompiledInInfo XXXXX_NAME(TEXT("XXXXX"),
    XXXX_REFLECT::ClassInfo, 
    UE_ARRAY_COUNT(XXXX_REFLECT::ClassInfo),
    nullptr, 
    0,
    XXXX_REFLECT::EnumInfo, 
    UE_ARRAY_COUNT(XXXX_REFLECT::EnumInfo)
);

static FRegisterCompiledInInfo会在程序启动时,静态创建这个结构体,从而实现了自动注册功能,但是此时还不能直接执行注册,主要是因为全局静态对象构建时机的不确定性, 所以我们先将注册信息保存起来,待后续合适的时机去处理待注册信息

2. 延迟注册

上文已经说了FRegisterCompiledInInfo会在构建时,将反射信息保存起来,简单的实现如下:

struct FRegisterCompiledInInfo
{
	template <typename ... Args>
	FRegisterCompiledInInfo(Args&& ... args)
	{
		RegisterCompiledInInfo(std::forward<Args>(args)...);
	}
};

// Multiple registrations
void RegisterCompiledInInfo(const TCHAR* PackageName, const FClassRegisterCompiledInInfo* ClassInfo, size_t NumClassInfo, const FStructRegisterCompiledInInfo* StructInfo, size_t NumStructInfo, const FEnumRegisterCompiledInInfo* EnumInfo, size_t NumEnumInfo)
{
    // 注册类信息
	for (size_t Index = 0; Index < NumClassInfo; ++Index)
	{
		const FClassRegisterCompiledInInfo& Info = ClassInfo[Index];
		RegisterCompiledInInfo(Info);
	}

    // 注册结构体信息
	for (size_t Index = 0; Index < NumStructInfo; ++Index)
	{
		const FStructRegisterCompiledInInfo& Info = StructInfo[Index];
		RegisterCompiledInInfo(Info);
	}

    // 注册枚举信息
	for (size_t Index = 0; Index < NumEnumInfo; ++Index)
	{
		const FEnumRegisterCompiledInInfo& Info = EnumInfo[Index];
		RegisterCompiledInInfo(Info);
	}
}

// 全局单例将传入的反射信息保存起来
void RegisterCompiledInInfo(FPackageRegistrationInfo& InInfo)
{
    FPackageDeferredRegistry::Get().AddRegistration(InInfo)
}

继续看RegisterCompiledInInfo(Info)方法

二. 自定义反射系统实现