I previously wrote two articles analyzing the implementation of reflection in UE, introducing the basic concepts of reflection in UE and some of the C++ features it relies on. This article will begin analyzing the specific process of UE’s reflection implementation.
The C++ standard does not have reflection features, and the reflection used in UE is a mechanism based on marker syntax and UHT scanning to generate auxiliary code. As David Wheeler famously said, “All problems in computer science can be solved by another level of indirection,” UHT does just that: it analyzes the marked code before actual compilation and generates real C++ code, collecting metadata regarding reflection types for runtime use.
UHT generates a large amount of code. To avoid organizational confusion in this article, I will mainly discuss the actual C++ code generated in generated.h after UHT processes reflection markers like GENERATED_BODY and UFUNCTION.
The code generated by UHT is located in generated.h and gen.cpp. The code in generated.h mostly defines some macros added to declared classes through compiler preprocessing to introduce common members, while the code in gen.cpp represents the specific code generated by UHT to describe class reflection information, maintaining separation of declaration and definition.