Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions CxxReflectionTests/src/RTLUnitTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,41 @@ int main()
const auto& classDateOpt = cxxMirror.getRecord("test_project", "Date");
std::cout << "\n\n[Reflection]-------Constructor/Destroctor call--------";
if (classDateOpt.has_value()) {

std::cout << "\nCreating \"Date\" instances via reflection..";

const auto& classDate = classDateOpt.value();
auto dateObj0 = classDate.newInstance();

if (dateObj0 == nullptr) {
std::cout << "\nError..! \"Date()\" ctor call via reflection failed.";
return 0;
}

const std::string& dateStr = "17/06/2024";
auto dateObj1 = classDate.newInstance(dateStr);

if (dateObj1 == nullptr) {
std::cout << "\nError..! \"Date(std::string)\" ctor call via reflection failed.";
return 0;
}


std::cout << "\n\n[Reflection]-------Member function call--------";
const auto& getDateOpt = classDate.getMethod("getDateAsString");
if (getDateOpt.has_value()) {
const auto& getDateStr = getDateOpt.value();
const auto& retOpt = getDateStr(dateObj1).invoke();

if (retOpt != nullptr) {
std::cout << "\ncall to Date::getDateAsString() return value : " << retOpt->get<std::string>().value();
}
}
else {
std::cout << "error..! couldn't resolve function call - Date::getDateAsString().";
}

std::cout << "\n\"Date\" instances created via reflection will destroy now.\n";
}

std::cout << std::endl;
Expand Down
2 changes: 2 additions & 0 deletions CxxTestProject/inc/Date.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ namespace test_project
~Date();
Date(const std::string& pDateStr);
const bool operator==(const Date& pOther) const;

std::string getDateAsString();
};
}
7 changes: 7 additions & 0 deletions CxxTestProject/src/Date.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,11 @@ namespace test_project
{
return (m_day == pOther.m_day && m_month == pOther.m_month && m_year == pOther.m_year);
}


std::string Date::getDateAsString()
{
std::cout << "\n[Method] Date::getDateAsString() called.";
return std::to_string(m_day) + "/" + std::to_string(m_month) + "/" + std::to_string(m_year);
}
}
2 changes: 1 addition & 1 deletion CxxTypeRegistration/inc/Reflection.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include "CxxMirror.h"
#include "ReflectionTemplateLib.h"

namespace rtl_tests {

Expand Down
4 changes: 3 additions & 1 deletion CxxTypeRegistration/src/Reflection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ namespace rtl_tests {
Reflect().nameSpace("test_project").record("Date").constructor<Date>().build(),

//Constructor registration, Date(std::string)
Reflect().nameSpace("test_project").record("Date").constructor<Date>().build<std::string>()
Reflect().nameSpace("test_project").record("Date").constructor<Date>().build<std::string>(),

Reflect().nameSpace("test_project").record("Date").function("getDateAsString").build(&Date::getDateAsString)
});

return cxxMirror;
Expand Down
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,15 @@ const CxxMirror& MyReflection()
Registration syntax is simple **Builder Pattern**,
```c++

Reflect().nameSpace("..") //use if type is enclosed in a namespace, pass namespace as string.
.record("..") //pass class/struct name as string.
.function("..") //pass function name as string.
.build(*); //pass function pointer.
Reflect().nameSpace("..") //use if type is enclosed in a namespace, pass namespace as string.
.record("..") //pass class/struct name as string.
.function("..") //pass function name as string.
.build(*); //pass function pointer.

Reflect().nameSpace("..")
.record("..")
.constructor<..>() //pass struct/class type as template parameter.
.build<..>(); //zero args for constructors, register constructor signature as template params.
Reflect().nameSpace("..")
.record("..")
.constructor<..>() //pass struct/class type as template parameter.
.build<..>(); //zero args for constructors, register constructor signature as template params.
```
- In main.cpp, Use **Person** class via Reflection without exposing the **Person Type**.
(*New underlying access-mechanism is in progress. These will not work currenty but final design will stay the same as below.*)
Expand Down Expand Up @@ -153,5 +153,6 @@ Create instance using overloaded constructor *(the one registered as **ctorArgs<
- Unit test cases (WIP)
- Class/Struct's Field reflection (Currently only methods are supported).
- Enum Class reflection.
- Exception handling (WIP)
- Access specifiers for reflection *(presently any Method/Field registerd is considered as public)*
- Light weight JSON Serialization/Deserialization feature.
- Light weight JSON Serialization/Deserialization feature.
2 changes: 2 additions & 0 deletions ReflectionTemplateLib/inc/Constants.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <type_traits>

namespace rtl {

const char* const NS_GLOBAL = "namespace_global";
Expand Down
4 changes: 2 additions & 2 deletions ReflectionTemplateLib/inc/ConstructorBuilder.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#pragma once

#include "Function.h"

namespace rtl {

class Function;

template<class _recordType>
class ConstructorBuilder
{
Expand Down
2 changes: 2 additions & 0 deletions ReflectionTemplateLib/inc/ConstructorBuilder.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@

#include "Function.h"
#include "ConstructorBuilder.h"

namespace rtl {
Expand Down
4 changes: 3 additions & 1 deletion ReflectionTemplateLib/inc/CxxMirror.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
#include <optional>
#include <unordered_map>

#include "RObject.hpp"
#include "NameSpace.h"

namespace rtl {

class Record;
class Function;

class CxxMirror
{
std::unordered_map<std::string, NameSpace> m_namespaces;
Expand Down
2 changes: 1 addition & 1 deletion ReflectionTemplateLib/inc/CxxMirrorBuilder.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

#include "Function.hpp"
#include "Constants.h"
#include "NameSpace.h"
#include "FunctionBuilder.h"
#include "ConstructorBuilder.hpp"

Expand Down
18 changes: 14 additions & 4 deletions ReflectionTemplateLib/inc/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
#include <string>
#include <memory>

#include "RObject.h"
#include "Constants.h"

namespace rtl {

class RObject;
class MethodInvoker;

class Function
{
const std::size_t m_functorId;
Expand All @@ -19,9 +21,12 @@ namespace rtl {
const std::string m_namespace;

Function(const std::string& pNamespace, const std::string& pClassName, const std::string& pFuncName,
const std::string& pSignature, const std::size_t& pSignatureId, const std::size_t& pFunctorId);
const std::string& pSignature, const std::size_t& pSignatureId, const std::size_t& pFunctorId);

template<class ..._args>
std::unique_ptr<RObject> execute(const std::unique_ptr<RObject>& pTarget, _args...params) const;

public:
public: friend MethodInvoker;

Function() = delete;

Expand All @@ -39,6 +44,11 @@ namespace rtl {
static const Function addConstructor(const std::string& pNamespace, const std::string& pRecord);

template<class _returnType, class ..._signature>
static const Function addFunctor(const std::string& pNamespace, const std::string& pRecord, const std::string& pFunction, _returnType(*pFunctor)(_signature...));
static const Function addFunctor(const std::string& pNamespace, const std::string& pRecord,
const std::string& pFunction, _returnType(*pFunctor)(_signature...));

template<class _recordType, class _returnType, class ..._signature>
static const Function addFunctor(const std::string& pNamespace, const std::string& pRecord,
const std::string& pFunction, _returnType(_recordType::* pFunctor)(_signature...));
};
}
28 changes: 26 additions & 2 deletions ReflectionTemplateLib/inc/Function.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include "TypeList.h"
#include "Function.h"
#include "Constants.h"
#include "FunctorContainer.hpp"

namespace rtl {
Expand All @@ -20,6 +19,19 @@ namespace rtl {
}


template<class ..._args>
inline std::unique_ptr<RObject> Function::execute(const std::unique_ptr<RObject>& pTarget, _args ...params) const
{
if (m_signatureId == FunctorContainer<_args...>::getContainerId()) {
return FunctorContainer<_args...>::reflectCall(pTarget, m_functorId, params...);
}
else {
assert(false && "Throw bad call exception");
}
return nullptr;
}


template<typename _recordType, class ..._ctorSignature>
inline const Function Function::addConstructor(const std::string& pNamespace, const std::string& pRecord)
{
Expand All @@ -35,7 +47,19 @@ namespace rtl {


template<class _returnType, class ..._signature>
inline const Function Function::addFunctor(const std::string& pNamespace, const std::string& pClassName, const std::string& pFunctionName, _returnType(*pFunctor)(_signature...))
inline const Function Function::addFunctor(const std::string& pNamespace, const std::string& pClassName,
const std::string& pFunctionName, _returnType(*pFunctor)(_signature...))
{
const std::size_t signatureId = FunctorContainer<_signature...>::getContainerId();
const std::size_t functorId = FunctorContainer<_signature...>::addFunctor(pFunctor);
const std::string& signature = "(" + TypeList<_signature...>::toString() + ")";
return Function(pNamespace, pClassName, pFunctionName, signature, signatureId, functorId);
}


template<class _recordType, class _returnType, class ..._signature>
inline const Function Function::addFunctor(const std::string& pNamespace, const std::string& pClassName,
const std::string& pFunctionName, _returnType(_recordType::* pFunctor)(_signature...))
{
const std::size_t signatureId = FunctorContainer<_signature...>::getContainerId();
const std::size_t functorId = FunctorContainer<_signature...>::addFunctor(pFunctor);
Expand Down
7 changes: 7 additions & 0 deletions ReflectionTemplateLib/inc/FunctionBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,12 @@ namespace rtl {
{
return Function::addFunctor(m_namespace, m_record, m_function, pFunctor);
}


template<class _recordType, class _returnType, class ..._signature>
inline constexpr const Function build(_returnType(_recordType::* pFunctor)(_signature...)) const
{
return Function::addFunctor(m_namespace, m_record, m_function, pFunctor);
}
};
}
18 changes: 15 additions & 3 deletions ReflectionTemplateLib/inc/FunctorContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,36 @@ namespace rtl {
public: friend class Function;

static const std::size_t& getContainerId();
using FunctorType = std::function < std::unique_ptr<RObject> (_signature...)>;

using FunctorType = std::function < std::unique_ptr<RObject> (_signature...) >;
using MethodPtrType = std::function < std::unique_ptr<RObject> (const std::unique_ptr<RObject>&, _signature...) >;

private:

static const std::size_t m_containerId;

static std::vector<FunctorType> m_functors;
static std::vector<MethodPtrType> m_methodPtrs;

template<class _returnType>
static int addFunctor(_returnType(*pFunctor)(_signature...), enable_if_same<_returnType, void>* _ = nullptr);
static int addFunctor(_returnType(*pFunctor)(_signature...), enable_if_same<_returnType, void> *_ = nullptr);

template<class _returnType>
static int addFunctor(_returnType(*pFunctor)(_signature...), enable_if_notSame<_returnType, void>* _ = nullptr);
static int addFunctor(_returnType(*pFunctor)(_signature...), enable_if_notSame<_returnType, void> *_ = nullptr);

template<class _recordType, class _returnType>
static int addFunctor(_returnType(_recordType::* pFunctor)(_signature...), enable_if_same<_returnType, void> *_ = nullptr);

template<class _recordType, class _returnType>
static int addFunctor(_returnType(_recordType::* pFunctor)(_signature...), enable_if_notSame<_returnType, void> *_ = nullptr);

template<class _recordType>
static int addConstructor(const std::string& pCtorType);

template<class ..._params>
static std::unique_ptr<RObject> reflectCall(std::size_t pFunctorId, _params..._args);

template<class ..._params>
static std::unique_ptr<RObject> reflectCall(const std::unique_ptr<RObject>& pTarget, std::size_t pFunctorId, _params..._args);
};
}
63 changes: 63 additions & 0 deletions ReflectionTemplateLib/inc/FunctorContainer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ namespace rtl {
std::vector<typename FunctorContainer<_signature...>::FunctorType> FunctorContainer<_signature...>::m_functors;


template<class ..._signature>
std::vector<typename FunctorContainer<_signature...>::MethodPtrType> FunctorContainer<_signature...>::m_methodPtrs;


template<class ..._signature>
inline const std::size_t& FunctorContainer<_signature...>::getContainerId()
{
Expand All @@ -38,6 +42,20 @@ namespace rtl {
}


template<class ..._signature>
template<class ..._params>
inline std::unique_ptr<RObject> FunctorContainer<_signature...>::reflectCall(const std::unique_ptr<RObject>& pTarget, std::size_t pFunctorId, _params ..._args)
{
if (pFunctorId < m_methodPtrs.size()) {
return m_methodPtrs.at(pFunctorId)(pTarget, _args...);
}
else {
assert(false && "Throw bad call exception");
}
return nullptr;
}


template<class ..._signature>
template<class _recordType>
inline int FunctorContainer<_signature...>::addConstructor(const std::string& pCtorType)
Expand Down Expand Up @@ -78,4 +96,49 @@ namespace rtl {
m_functors.push_back(functor);
return (m_functors.size() - 1);
}


template<class ..._signature>
template<class _recordType, class _returnType>
inline int FunctorContainer<_signature...>::addFunctor(_returnType(_recordType::* pFunctor)(_signature...), enable_if_same<_returnType, void> *_)
{
const auto functor = [=](const std::unique_ptr<RObject>& pTargetObj, _signature...params)->std::unique_ptr<RObject>
{
auto targetObj = pTargetObj->get<_recordType*>();
if (targetObj.has_value())
{
_recordType* target = targetObj.value();
(target->*pFunctor)(params...);
}
else {
assert(false && "Throw bad call exception");
}
return nullptr;
};
m_methodPtrs.push_back(functor);
return (m_methodPtrs.size() - 1);
}


template<class ..._signature>
template<class _recordType, class _returnType>
inline int FunctorContainer<_signature...>::addFunctor(_returnType(_recordType::* pFunctor)(_signature...), enable_if_notSame<_returnType, void> *_)
{
const auto functor = [=](const std::unique_ptr<RObject>& pTargetObj, _signature...params)->std::unique_ptr<RObject>
{
auto targetObj = pTargetObj->get<_recordType*>();
if (targetObj.has_value())
{
_recordType* target = targetObj.value();
const auto& retObj = (target->*pFunctor)(params...);
return std::unique_ptr<RObject>(new ReturnObject<_returnType>(TypeList<_returnType>::toString(), retObj));
}
else {
assert(false && "Throw bad call exception");
return nullptr;
}
};
m_methodPtrs.push_back(functor);
return (m_methodPtrs.size() - 1);
}
}
Loading