项目作者: stevinz

项目描述 :
Small, flexible, single header library for runtime reflection and meta data in C++11.
高级语言: C++
项目地址: git://github.com/stevinz/reflect.git
创建时间: 2021-03-20T18:33:23Z
项目社区:https://github.com/stevinz/reflect

开源协议:MIT License

下载


Reflect

Small, flexible, single-header library for aggregate (struct / class) runtime reflection and meta data using C++11 features. Minimal STL usage, no other dependencies.


Installation

  • Copy ‘reflect.h’ to project

  • In ONE cpp file, define REGISTER_REFLECTION:

    1. #define REGISTER_REFLECTION
    2. #include "reflect.h"
    3. #include "my_struct_1.h"
    4. #include "my_struct_2.h"
    5. #include etc...
  • Classes / Structs should be simple aggregate types (standard layout)

  • BEFORE using reflection functions, make one call to

    1. InitializeReflection();


Usage

Registration in Header File, example: “transform.h”

  1. #ifndef TRANSFORM2D_H
  2. #define TRANSFORM2D_H
  3. #include "reflect.h"
  4. struct Transform2D {
  5. int width;
  6. int height;
  7. std::vector<double> position;
  8. std::string text;
  9. REFLECT();
  10. }
  11. #ifdef REGISTER_REFLECTION
  12. REFLECT_CLASS(Transform2D)
  13. REFLECT_MEMBER(width)
  14. REFLECT_MEMBER(height)
  15. REFLECT_MEMBER(position)
  16. REFLECT_MEMBER(text)
  17. REFLECT_END(Transform2D)
  18. #endif
  19. #endif // TRANSFORM2D_H


In Code

Initialize class instance

  1. Transform2D t { };
  2. t.width = 100;
  3. t.height = 100;
  4. t.position = std::vector<double>({1.0, 2.0, 3.0});
  5. t.text = "Hello world!";

TypeData Object

  1. // Class TypeData
  2. TypeData data = ClassData<Transform2D>(); // By class type
  3. TypeData data = ClassData(t); // By class instance
  4. TypeData data = ClassData(type_hash); // By class type hash
  5. TypeData data = ClassData("Transform2D"); // By class name
  6. // Member TypeData
  7. TypeData data = MemberData<Transform2D>(0); // By class type, member index
  8. TypeData data = MemberData<Transform2D>("width"); // By class type, member name
  9. TypeData data = MemberData(t, 0); // By class instance, member index
  10. TypeData data = MemberData(t, "width"); // By class instance, member name
  11. TypeData data = MemberData(type_hash, 0); // By class type hash, member index
  12. TypeData data = MemberData(type_hash, "width"); // By class type hash, member name

Get / Set Member Variables

  • Use the ClassMember(class_instance, member_data) function to return a reference to a member variable. This function requires the return type, a class instance (can be void* or class type), and a member variable TypeData object. Before calling ClassMember<>(), member variable type can be checked by comparing to types using helper function TypeHashID()
    ```cpp
    // Member Variable by Index
    TypeData member = MemberData(t, 0);
    if (member.type_hash == TypeHashID()) {
    // Create reference to member
    int& width = ClassMember(&t, member);
    // Can now set member variable directly
    width = 120;
    }

// Member Variable by Name
TypeData member = MemberData(t, “position”);
if (member.type_hash == TypeHashID>()) {
// Create reference to member
std::vector& position = ClassMember>(&t, member);
// Can now set member variable directly
position = { 2.0, 4.0, 6.0 };
}

  1. <br />
  2. ## Iterating Members / Properties
  3. ```cpp
  4. int member_count = ClassData(t).member_count;
  5. for (int index = 0; index < member_count; ++index) {
  6. TypeData member = MemberData(t, index);
  7. std::cout << " Index: " << member.index << ", ";
  8. std::cout << " Name: " << member.name << ", ";
  9. std::cout << " Title: " << member.title << ", ";
  10. std::cout << " Value: ";
  11. if (member.type_hash == TypeHashID<int>()) {
  12. std::cout << ClassMember<int>(&t, member);
  13. } else if (member.type_hash == TypeHashID<std::string>()) {
  14. std::cout << ClassMember<std::string>(&t, member);
  15. } else if (member.type_hash == TypeHashID<std::vector<double>>()) {
  16. std::vector<double>& vec = ClassMember<std::vector<double>>(&t, member);
  17. for (auto& number : vec) {
  18. std::cout << number << ", ";
  19. }
  20. }
  21. }


Data from Unknown Class Type

  • If using with an entity component system, it’s possible you may not have access to class type at runtime. Often a collection of components are stored in a container of void pointers. Somewhere in your code when your class is initialized, store the component class TypeHash:
    1. TypeHash saved_hash = ClassData(t).type_hash;
    2. void* class_pointer = (void*)(&t);
  • Later (if your components are stored as void pointers in an array / vector / etc. with other components) you may still access the member variables of the component without casting the component back to the original type. This is done by using the saved_hash from earlier:
    1. using vec = std::vector<double>;
    2. TypeData member = MemberData(saved_hash, 3);
    3. if (member.type_hash == TypeHashID<vec>()) {
    4. vec& rotation = ClassMember<vec>(class_pointer, member);
    5. std::cout << " Rotation X: " << rotation[0];
    6. std::cout << ", Rotation Y: " << rotation[1];
    7. std::cout << ", Rotation Z: " << rotation[2];
    8. }


User Meta Data

Registration in Header File, example: “transform.h”

  • Meta data can by stored as std::string within a class or member type. Set user meta data at compile time using CLASS_META_DATA and MEMBER_META_DATA in the class header file with (int, string) or (sting, string) pairs:
    1. #ifdef REGISTER_REFLECTION
    2. REFLECT_CLASS(Transform2D)
    3. CLASS_META_DATA(META_DATA_DESCRIPTION, "Describes object in 2D space.")
    4. CLASS_META_DATA("icon", "assets/transform.png")
    5. REFLECT_MEMBER(width)
    6. MEMBER_META_DATA(META_DATA_DESCRIPTION, "Width of this object.")
    7. REFLECT_MEMBER(height)
    8. MEMBER_META_DATA(META_DATA_DESCRIPTION, "Height of this object.")
    9. REFLECT_MEMBER(position)
    10. MEMBER_META_DATA(META_DATA_HIDDEN, "true")
    11. MEMBER_META_DATA("tooltip", "Pos")
    12. REFLECT_END(Transform2D)
    13. #endif

Get / Set Meta Data

  • BY REFERENCE, pass a TypeData object (class or member, this can be retrieved many different ways as shown earlier) to the meta data functions to get / set meta data at runtime:
    ```cpp
    // TypeData from class
    TypeData& type_data = ClassData();
    // or from member variable
    TypeData& type_data = MemberData(“width”);

// Get meta data
std::string description = GetMetaData(type_data, META_DATA_DESCRIPTION);
std::string icon_file = GetMetaData(type_data, “icon”);

// Set meta data
SetMetaData(type_data, META_DATA_DESCRIPTION, description);
SetMetaData(type_data, “icon”, icon_file);
```


Portability

Tested and compiled with:

  • GCC 4.2.1
  • Emscripten 1.38.43