From d426f832d37cb11de425869169c6dde214786c5a Mon Sep 17 00:00:00 2001 From: JomiXedYu Date: Sun, 14 May 2023 16:28:01 +0800 Subject: [PATCH] method reflection --- CoreLib/Delegate.h | 6 +- CoreLib/Reflection.cpp | 19 ++++--- CoreLib/Reflection.h | 109 ++++++++++++++++++++++++++++++------- Example/TestReflection.cpp | 59 +++++++------------- 4 files changed, 125 insertions(+), 68 deletions(-) diff --git a/CoreLib/Delegate.h b/CoreLib/Delegate.h index 391fa80..1bdbf1c 100644 --- a/CoreLib/Delegate.h +++ b/CoreLib/Delegate.h @@ -179,11 +179,11 @@ namespace jxcorlib CORELIB_DEF_TEMPLATE_TYPE(AssemblyObject_jxcorlib, jxcorlib::FunctionDelegate, Delegate, TReturn, TArgs...); static_assert(sizeof...(TArgs) <= 16); - + public: using This = FunctionDelegate; using FunctionType = std::function; using FunctionPointer = TReturn(*)(TArgs...); - + private: enum class FunctionInfoType { Static, Lambda, Member @@ -262,7 +262,7 @@ namespace jxcorlib } }; - protected: + public: FunctionInfo* func_ptr_; FunctionDelegate(FunctionPointer funcptr) : func_ptr_(new StaticFunctionInfo(funcptr)) {} diff --git a/CoreLib/Reflection.cpp b/CoreLib/Reflection.cpp index f0dea80..b7d01f9 100644 --- a/CoreLib/Reflection.cpp +++ b/CoreLib/Reflection.cpp @@ -62,17 +62,22 @@ namespace jxcorlib } MethodInfo::MethodInfo( - const string& name, bool is_public, - ParameterInfo* ret_type, array_list&& params_infos, bool is_abstract - ) : base(name, is_public), - ret_type_(ret_type), param_types_(params_infos), is_abstract_(is_abstract) + const string& name, + bool isPublic, + bool isStatic, + ParameterInfo* retType, + array_list&& paramsInfos, + bool isAbstract, + std::unique_ptr&& delegate + ) : base(name, isPublic), + m_isStatic(isStatic), + m_retType(retType), m_paramTypes(paramsInfos), m_isAbstract(isAbstract), m_delegate(std::move(delegate)) { } - Object_sp MethodInfo::Invoke(Object* instance, array_list&& params) const + Object_sp MethodInfo::Invoke(Object_rsp instance, array_list&& params) const { - - return nullptr; + return this->m_delegate->CreateDelegate(instance)->DynamicInvoke(params); } diff --git a/CoreLib/Reflection.h b/CoreLib/Reflection.h index a0cc966..4896595 100644 --- a/CoreLib/Reflection.h +++ b/CoreLib/Reflection.h @@ -14,7 +14,7 @@ #include "Assembly.h" #include "BasicTypes.h" #include "Enum.h" - +#include "Delegate.h" #include #include #include @@ -45,18 +45,61 @@ } \ } __corelib_refl_##NAME##_; -#define CORELIB_REFL_DECL_FUNC(NAME) \ - static inline struct __corelib_refl_##NAME \ +#define CORELIB_REFL_DECL_STATICMETHOD(METHOD) \ + static inline struct __corelib_refl_##METHOD \ { \ - __corelib_refl_##NAME() \ + __corelib_refl_##METHOD() \ { \ array_list infos; \ - ReflectionBuilder::CreateMethodParameterInfos(NAME, &infos); \ + ReflectionBuilder::GenMethodParameterInfos(&ThisClass::METHOD, &infos); \ + auto deleg = std::unique_ptr(new StaticMethodDescription{ &ThisClass::METHOD }); \ + ReflectionBuilder::CreateMethodInfo(StaticType(), #METHOD, true, true, std::move(infos), std::move(deleg)); \ } \ - } __corelib_refl_##NAME##_; + } __corelib_refl_##METHOD##_; + +#define CORELIB_REFL_DECL_METHOD(METHOD) \ + static inline struct __corelib_refl_##METHOD \ + { \ + __corelib_refl_##METHOD() \ + { \ + array_list infos; \ + ReflectionBuilder::GenMethodParameterInfos(&ThisClass::METHOD, &infos); \ + auto deleg = std::unique_ptr(new MemberMethodDescription{ &ThisClass::METHOD }); \ + ReflectionBuilder::CreateMethodInfo(StaticType(), #METHOD, true, false, std::move(infos), std::move(deleg)); \ + } \ + } __corelib_refl_##METHOD##_; namespace jxcorlib { + struct MethodDescription + { + virtual sptr CreateDelegate(Object_rsp target) = 0; + ~MethodDescription() + { + int a = 3; + } + }; + template + struct StaticMethodDescription : public MethodDescription + { + StaticMethodDescription(TReturn(*ptr)(TArgs...)) : m_ptr(ptr) {} + virtual sptr CreateDelegate(Object_rsp target) + { + return mksptr(new FunctionDelegate(m_ptr)); + } + TReturn(*m_ptr)(TArgs...); + }; + template + struct MemberMethodDescription : public MethodDescription + { + MemberMethodDescription(TReturn(TClass::* ptr)(TArgs...)) : m_ptr(ptr) {} + virtual sptr CreateDelegate(Object_rsp target) + { + return mksptr(new FunctionDelegate(sptr_cast(target), m_ptr)); + } + TReturn(TClass::* m_ptr)(TArgs...); + }; + class Attribute; class TypeInfo : public Object @@ -164,30 +207,45 @@ namespace jxcorlib m_isRref(isRref) {} }; - //TODO class MethodInfo final : public MemberInfo { CORELIB_DEF_TYPE(AssemblyObject_jxcorlib, jxcorlib::MethodInfo, MemberInfo); friend class ReflectionBuilder; protected: - array_list param_types_; - ParameterInfo* ret_type_; - bool is_abstract_; + array_list m_paramTypes; + ParameterInfo* m_retType; + bool m_isAbstract; + bool m_isStatic; + std::unique_ptr m_delegate; public: - const std::vector& get_parameter_infos() const noexcept { return this->param_types_; } - ParameterInfo* get_return_type() const noexcept { return this->ret_type_; } - bool is_abstract() const { return this->is_abstract_; } + const std::vector& GetParameterInfos() const noexcept { return this->m_paramTypes; } + ParameterInfo* GetReturnType() const noexcept { return this->m_retType; } + bool IsAbstract() const { return this->m_isAbstract; } + bool IsStatic() const { return this->m_isStatic; } public: MethodInfo( - const string& name, bool is_public, - ParameterInfo* ret_type, array_list&& params_infos, bool is_abstract); + const string& name, + bool isPublic, + bool isStatic, + ParameterInfo* retType, + array_list&& paramsInfos, + bool isAbstract, + std::unique_ptr&& delegate); + MethodInfo(const MethodInfo& right) = delete; MethodInfo(MethodInfo&& right) = delete; public: - Object_sp Invoke(Object* instance, array_list&& params) const; + template + sptr CreateDelegate(Object_rsp target) + { + return sptr_cast(this->m_delegate->CreateDelegate(target)); + } + + Object_sp Invoke(Object_rsp instance, array_list&& params) const; }; + class ReflectionBuilder { private: @@ -241,16 +299,29 @@ namespace jxcorlib public: template - static void CreateMethodParameterInfos(R(*p)(P...), array_list* out) + static void GenMethodParameterInfos(R(*p)(P...), array_list* out) { _GetParameters(out, GenNullptr

()...); } + template + static void GenMethodParameterInfos(R(TClass::*p)(P...), array_list* out) + { + _GetParameters(out, GenNullptr

()...); + } - static void CreateMethodInfo(Type* type, const string& name, bool is_public, array_list&& info) + static void CreateMethodInfo( + Type* type, + const string& name, + bool isPublic, + bool isStatic, + array_list&& info, + std::unique_ptr&& delegate) { //todo: return value - type->_AddMemberInfo(new MethodInfo(name, is_public, nullptr, std::move(info), false)); + auto methodInfo = new MethodInfo(name, isPublic, isStatic, nullptr, std::move(info), false, std::move(delegate)); + type->_AddMemberInfo(methodInfo); + } }; } diff --git a/Example/TestReflection.cpp b/Example/TestReflection.cpp index 5088e5b..ebd62ac 100644 --- a/Example/TestReflection.cpp +++ b/Example/TestReflection.cpp @@ -3,7 +3,7 @@ #include #include #include - +#include using namespace jxcorlib; @@ -27,10 +27,10 @@ namespace space } -struct gen_lambda +struct MethodReflectionGenerator { template - static std::function&&)> get(R(*ptr)()) + static std::function&&)> Generate(R(*ptr)()) { return [ptr](array_list&& objs) -> Object_sp { auto ret = ptr(); @@ -43,7 +43,7 @@ struct gen_lambda } template - static std::function&&)> get(R(*ptr)(P1)) + static std::function&&)> Generate(R(*ptr)(P1)) { return [ptr](array_list&& objs) -> Object_sp { auto ret = ptr(UnboxUtil::Unbox(objs[0])); @@ -52,13 +52,11 @@ struct gen_lambda } template - static std::function&&)> get(R(*ptr)(P1, P2)) + static auto Generate(R(*ptr)(P1, P2)) { - return [ptr](array_list&& objs) -> Object_sp { - auto ret = ptr(UnboxUtil::Unbox(objs[0]), UnboxUtil::Unbox(objs[1])); - return BoxUtil::Box(ret); - }; + return FunctionDelegate(ptr); } + }; class DataModel : public Object @@ -69,40 +67,18 @@ class DataModel : public Object CORELIB_REFL_DECL_FIELD(id); int id = 0; public: - CORELIB_REFL_DECL_FIELD(is_human); bool is_human = true; CORELIB_REFL_DECL_FIELD(name); sptr name; + CORELIB_REFL_DECL_STATICMETHOD(Add); + static int Add(int32_t a, int64_t b) { return a + int(b); } + CORELIB_REFL_DECL_METHOD(Minus); + int Minus(int32_t a, int64_t b) { return a - int(b); } - - static int GetNum() - { - return 3; - } - - static int AddOne(int32_t a, int64_t b) - { - return a + int(b); - } - - static inline struct __corelib_refl_AddOne - { - __corelib_refl_AddOne() - { - array_list infos; - ReflectionBuilder::CreateMethodParameterInfos(AddOne, &infos); - ReflectionBuilder::CreateMethodInfo(StaticType(), "AddOne", true, std::move(infos)); - auto lambd = [](array_list&& objs) -> Object_sp { - auto ret = AddOne(UnboxUtil::Unbox(objs[0]), UnboxUtil::Unbox(objs[1])); - return BoxUtil::Box(ret); - }; - gen_lambda::get(AddOne); - } - } __corelib_refl_AddOne_; }; @@ -146,8 +122,13 @@ void TestReflection() assert(value == obj); - MethodInfo* minfo = cltypeof()->GetMethodInfo("AddOne"); - assert(minfo->get_parameter_infos().at(0)->GetParamType() == cltypeof()); - assert(minfo->get_parameter_infos().at(1)->GetParamType() == cltypeof()); - minfo->Invoke(model, {}); + MethodInfo* minfo = cltypeof()->GetMethodInfo("Add"); + assert(minfo->GetParameterInfos().at(0)->GetParamType() == cltypeof()); + assert(minfo->GetParameterInfos().at(1)->GetParamType() == cltypeof()); + + auto minfoRet1 = minfo->Invoke(nullptr, { mkbox(2), mkbox(3) }); + assert(UnboxUtil::Unbox(minfoRet1) == 5); + + auto minfoRet2 = cltypeof()->GetMethodInfo("Minus")->Invoke(mksptr(new DataModel), {mkbox(2), mkbox(5)}); + assert(UnboxUtil::Unbox(minfoRet2) == -3); } \ No newline at end of file