Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Cross-platform C++17 Runtime Reflection Library

License

NotificationsYou must be signed in to change notification settings

jsoysouvanh/Refureku

Repository files navigation

License: MITLatest Releasecodecovdocumentation

WindowsLinuxMacOS

Overview

Refureku is a powerful C++17 runtime reflection dynamic library.
It is split in 2 parts:

  • The code generator is aKodgen generation module. It handles the reflection code generation.
  • The actual dynamic library containing the reflection API that is linked to the target program.

Checkthe Wiki to get started!

Features

  • Reflect namespaces, classes, (static) methods, (static) fields, variables, functions, enums and enum values
  • Support runtime loaded/unloaded dynamic library reflection
  • Support class template reflection, as well as multiple inheritance
  • Entities do not need to be included to be manipulated
  • Reflected entities can be retrieved by name, id or predicate
  • Read/write reflected fields/variables value
  • Call reflected functions/methods
  • Instantiate reflected classes without access to their static type
  • Access dynamic type of an object instance through a base pointer/reference
  • Powerful property system allowing to attach custom metadata to any entity (C# attributes)
  • Reflection metadata is regenerated only when a file has changed
  • The library doesn't impose its own macro syntax: the user is free to define it
  • Highly flexible and customizable code generation

Design goals

Refureku was initially developed with game engine development in mind, which greatly influenced the global design and architecture. The usage was mostly inspired by UE4, and the API by the C# native reflection system.

The concept is simple: you write what you want to reflect once, include the generated files, and the code generator does the rest. Users don't have any extra step to care about. Reflected entities are automatically registered to the reflection system and available right away. Manual reflection was an absolute no-go because it is error prone and time-consuming.

Another point addressed by this library is the reflection syntax. It is sometimes annoying to be tied to the macro syntax of a third party library, especially when it is heavily used accross a project. UsingRefureku xKodgen, the user has full control over the generated files / macros names to make the reflection integrate well in any project.

Another key point of Kodgen is that it is simple to insert and mix custom generated code to the reflection generated code. TheRefureku code generator is a simple module added to the Kodgen generator. Users can create and add up as many code generation modules as they want to Kodgen, allowing custom generated code injection to the whole codebase without changing a single line of code in the target program.

Examples

All features in a single header file

#include<Refureku/Refureku.h>

Reflect a class

//TestClass.h#pragma once#include"Generated/TestClass.rfkh.h"classCLASS() TestClass{FIELD()int _intField;METHOD()voidtestMethod();    TestClass_GENERATED};File_TestClass_GENERATED
//TestClass.cpp, or any source file being part of your project#include"Generated/TestClass.rfks.h"

Get a class metadata

//From namerfk::Classconst* c = rfk::getDatabase().getFileLevelClassByName("TestClass");//From static typerfk::Classconst& c2 = TestClass::staticGetArchetype();//From reflected/unreflected typerfk::Archetypeconst* c3 = rfk::getArchetype<TestClass>();//nullptr if not reflected

Get class metadata from base pointer

This feature is only available to classes that publicly derive from rfk::Object (#include <Refureku/Object.h>).

TestClass instance;rfk::Objectconst* instancePtr = &instance;rfk::Classconst& archetype = instancePtr->getArchetype();

Manipulate fields

//Get fieldrfk::Fieldconst* field = TestClass::staticGetArchetype().getFieldByName("_intField");TestClass instance;//Read field valueint value = field->get<int>(instance);//Write field valuefield->set(instance,3);

Manipulate methods

//Get methodrfk::Methodconst* method = TestClass::staticGetArchetype().getMethodByName("testMethod");TestClass instance;//Call method without argumentsmethod->invoke(instance);//With arguments and returned valueint returnedValue = method->invoke<int>(instance,1,2,3);

Instantiate a class

rfk::Classconst* c = rfk::getDatabase().getFileLevelClassByName("TestClass");//Instantiate from default ctorrfk::SharedPtr<TestClass> instance = c->makeSharedInstance<TestClass>();//If TestClass has a base class, we can dorfk::SharedPtr<BaseClass> instance2 = c->makeSharedInstance<BaseClass>();

It is also possible to instantiate a class with parameters, by providing a custom instantiator when declaring the class:

//TestClass2.h#pragma once#include<Refureku/Properties/Instantiator.h>#include"Generated/TestClass2.rfkh.h"classCLASS() TestClass2 : public BaseClass{METHOD(rfk::Instantiator)static rfk::SharedPtr<TestClass2>customInstantiator(int i)    {//Use this if you don't need custom deleter//return rfk::makeShared<TestClass2>();//Use this if you want to provide a custom deleterreturn rfk::SharedPtr<TestClass2>(newTestClass2(), [](TestClass2* ptr)                {delete ptr;//Simple delete for example simplicity                });    }    TestClass2_GENERATED};File_TestClass2_GENERATED
//TestClass2.cpp#include"Generated/TestClass2.rfks.h"
rfk::Classconst* c2 = rfk::getDatabase().getFileLevelClassByName("TestClass2");//Call customInstantiatorrfk::SharedPtr<BaseClass> instance3 = c2->makeSharedInstance<BaseClass>(42);

Create custom properties

//ExampleProperty.h#pragma once#include<Refureku/Properties/PropertySettings.h>#include"Generated/ExampleProperty.rfkh.h"classCLASS(rfk::PropertySettings(rfk::EEntityKind::Struct | rfk::EEntityKind::Class))    ExampleProperty : public rfk::Property{public:int someData;ExampleProperty(int data):            someData{data}        {}    ExampleProperty_GENERATED};File_ExampleProperty_GENERATED
//ExampleProperty.cpp, or any source file being part of your project#include"Generated/ExampleProperty.rfks.h"

Then, we can attach ExampleProperty to any reflected struct or class, as specified by the first argument of PropertySettings. Attaching the property to any other entity will trigger a compilation error with an explicit error message.

//TestClass3.h#pragma once#include"ExampleProperty.h"//Include the custom property first#include"Generated/TestClass3.rfkh.h"classCLASS(ExampleProperty(42)) TestClass3{    TestClass3_GENERATED};File_TestClass3_GENERATED
//TestClass3.cpp#include"Generated/TestClass3.rfks.h"

Read entity properties

rfk::Classconst* c = rfk::getDatabase().getFileLevelClassByName("TestClass3");//From namerfk::Propertyconst* prop = c->getPropertyByName("ExampleProperty");//From static typeExamplePropertyconst* prop2 = c->getProperty<ExampleProperty>();

Cross-platform compatibility

This library has been tested and is stable on the following configurations:

  • Microsoft Windows Server | MSVC 19.29.30133.0
  • Linux 20.04 | Clang 7.0.1, Clang 8.0.1, Clang 9.0.1, Clang 10.0.0, Clang 11.0.0
  • Linux 20.04 | GNU 8.4.0, GNU 9.3.0, GNU 10.3.0, GNU 11.1.0
  • Mac OS X 10.15.7 | AppleClang 12.0.0

Known issues

  • (MSVC only) Issues when reflecting class templates with only template template parameters, seethis issue.
  • (MSVC only) Compilation error when reflect protected/private nested class templates
  • If a reflected namespace is shared among different dynamic libraries, specific properties bound to each of those libraries are not removed when they are unloaded.

[8]ページ先頭

©2009-2025 Movatter.jp