Description
C++ can not reflect on classes as such this project were created. This project uses Clang LLVM to reflect files and generate code to set up reflection data that exposes objects, variables and functions.
This allows a program to dynamically read and call functions. This is useful for scripting as data containers such as classes and structs can now be read and modified.
Clang
The Clang project provides a language front-end and tooling infrastructure for languages in the C language family (C, C++, Objective C/C++, OpenCL, and CUDA) for the LLVM project.
I choose Clang instead of other tools as it is gives more information, faster compilation, more detailed error reports.
The time consuming factor we faced when implementing the scripting system was that we had to manually write all class functions, variables and base class connections, which our scripting system should have access to since C++ cant reflect.
To automatize this step I created a File Reflection program that creates all relative data we needed for the scripting system.
To describe how the file reflection works, I have divided the process into three steps: Find Files, Reflect and Generate Data. Where I will go through how it works!
When the program starts, it is important for the program to find where all the header files exists within the folder structure. So when the program starts it creates a tree-like structure of where all header files lies (it saves the paths in a vector and processed to the next stage in the process).
After the path have been found and stored in a vector, the file will get reflected with a Clang function named "clang_visitChildren".
This function allows for traversal through a abstract syntax using cursors, this allowed me to extract data from the cursors and interpret them as data that we needed (class, functions, variables and base classes). The Reflector will begin by finding all macros inside the code that serve as Meta data for the reflector. This data is used to determine if a variable, function or class should reflected. If a Class has a base class of a component, it will treat it as being marked for reflection (a reflected class will reflect all public information).
Structure of the Reflector class:
Once the reflector has processed every file, the data is then used to create a file with the reflected information for a program it was intended for.
Each reflected entity inherit from Reflection_Base that describe the reflection such as:
Namespace, name, decals, global id (Hashed namespace and name), local id (name) and type (Base data type, function, container). This allows for an interface to find and use classes without using Types. When a program starts it will populate it's data with the reflected data and create interfaces for functions and variables with the FunctionCallManager.
The project allows us to interact with the reflected data and determine what and which it is. With this we can use this potentially for Scripting, Editor, Dynamic calls (such as UI Buttons or in game events).
It should be possible to replace vectors with arrays that we can create on compile time instead of initialization.