Skip to content

Commit

Permalink
method reflection
Browse files Browse the repository at this point in the history
  • Loading branch information
Jomixedyu committed May 14, 2023
1 parent eb5f721 commit d426f83
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 68 deletions.
6 changes: 3 additions & 3 deletions CoreLib/Delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<TReturn, TArgs...>;
using FunctionType = std::function<TReturn(TArgs...)>;
using FunctionPointer = TReturn(*)(TArgs...);

private:
enum class FunctionInfoType
{
Static, Lambda, Member
Expand Down Expand Up @@ -262,7 +262,7 @@ namespace jxcorlib
}
};

protected:
public:
FunctionInfo* func_ptr_;

FunctionDelegate(FunctionPointer funcptr) : func_ptr_(new StaticFunctionInfo(funcptr)) {}
Expand Down
19 changes: 12 additions & 7 deletions CoreLib/Reflection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,22 @@ namespace jxcorlib
}

MethodInfo::MethodInfo(
const string& name, bool is_public,
ParameterInfo* ret_type, array_list<ParameterInfo*>&& 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<ParameterInfo*>&& paramsInfos,
bool isAbstract,
std::unique_ptr<MethodDescription>&& 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<Object_sp>&& params) const
Object_sp MethodInfo::Invoke(Object_rsp instance, array_list<Object_sp>&& params) const
{

return nullptr;
return this->m_delegate->CreateDelegate(instance)->DynamicInvoke(params);
}


Expand Down
109 changes: 90 additions & 19 deletions CoreLib/Reflection.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include "Assembly.h"
#include "BasicTypes.h"
#include "Enum.h"

#include "Delegate.h"
#include <functional>
#include <any>
#include <memory>
Expand Down Expand Up @@ -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<ParameterInfo*> infos; \
ReflectionBuilder::CreateMethodParameterInfos(NAME, &infos); \
ReflectionBuilder::GenMethodParameterInfos(&ThisClass::METHOD, &infos); \
auto deleg = std::unique_ptr<MethodDescription>(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<ParameterInfo*> infos; \
ReflectionBuilder::GenMethodParameterInfos(&ThisClass::METHOD, &infos); \
auto deleg = std::unique_ptr<MethodDescription>(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<Delegate> CreateDelegate(Object_rsp target) = 0;
~MethodDescription()
{
int a = 3;
}
};
template<typename TReturn, typename... TArgs>
struct StaticMethodDescription : public MethodDescription
{
StaticMethodDescription(TReturn(*ptr)(TArgs...)) : m_ptr(ptr) {}
virtual sptr<Delegate> CreateDelegate(Object_rsp target)
{
return mksptr(new FunctionDelegate<TReturn, TArgs...>(m_ptr));
}
TReturn(*m_ptr)(TArgs...);
};
template<typename TClass, typename TReturn, typename... TArgs>
struct MemberMethodDescription : public MethodDescription
{
MemberMethodDescription(TReturn(TClass::* ptr)(TArgs...)) : m_ptr(ptr) {}
virtual sptr<Delegate> CreateDelegate(Object_rsp target)
{
return mksptr(new FunctionDelegate<TReturn, TArgs...>(sptr_cast<TClass>(target), m_ptr));
}
TReturn(TClass::* m_ptr)(TArgs...);
};

class Attribute;

class TypeInfo : public Object
Expand Down Expand Up @@ -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<ParameterInfo*> param_types_;
ParameterInfo* ret_type_;
bool is_abstract_;
array_list<ParameterInfo*> m_paramTypes;
ParameterInfo* m_retType;
bool m_isAbstract;
bool m_isStatic;
std::unique_ptr<MethodDescription> m_delegate;
public:
const std::vector<ParameterInfo*>& 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<ParameterInfo*>& 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<ParameterInfo*>&& params_infos, bool is_abstract);
const string& name,
bool isPublic,
bool isStatic,
ParameterInfo* retType,
array_list<ParameterInfo*>&& paramsInfos,
bool isAbstract,
std::unique_ptr<MethodDescription>&& delegate);

MethodInfo(const MethodInfo& right) = delete;
MethodInfo(MethodInfo&& right) = delete;
public:
Object_sp Invoke(Object* instance, array_list<Object_sp>&& params) const;
template<typename T>
sptr<T> CreateDelegate(Object_rsp target)
{
return sptr_cast<T>(this->m_delegate->CreateDelegate(target));
}

Object_sp Invoke(Object_rsp instance, array_list<Object_sp>&& params) const;
};



class ReflectionBuilder
{
private:
Expand Down Expand Up @@ -241,16 +299,29 @@ namespace jxcorlib
public:

template<typename R, typename... P>
static void CreateMethodParameterInfos(R(*p)(P...), array_list<ParameterInfo*>* out)
static void GenMethodParameterInfos(R(*p)(P...), array_list<ParameterInfo*>* out)
{
_GetParameters(out, GenNullptr<P>()...);
}

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

static void CreateMethodInfo(Type* type, const string& name, bool is_public, array_list<ParameterInfo*>&& info)
static void CreateMethodInfo(
Type* type,
const string& name,
bool isPublic,
bool isStatic,
array_list<ParameterInfo*>&& info,
std::unique_ptr<MethodDescription>&& 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);

}
};
}
59 changes: 20 additions & 39 deletions Example/TestReflection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <functional>
#include <map>
#include <iostream>

#include <CoreLib/Delegate.h>

using namespace jxcorlib;

Expand All @@ -27,10 +27,10 @@ namespace space
}


struct gen_lambda
struct MethodReflectionGenerator
{
template<typename R>
static std::function<Object_sp(array_list<Object_sp>&&)> get(R(*ptr)())
static std::function<Object_sp(array_list<Object_sp>&&)> Generate(R(*ptr)())
{
return [ptr](array_list<Object_sp>&& objs) -> Object_sp {
auto ret = ptr();
Expand All @@ -43,7 +43,7 @@ struct gen_lambda
}

template<typename R, typename P1>
static std::function<Object_sp(array_list<Object_sp>&&)> get(R(*ptr)(P1))
static std::function<Object_sp(array_list<Object_sp>&&)> Generate(R(*ptr)(P1))
{
return [ptr](array_list<Object_sp>&& objs) -> Object_sp {
auto ret = ptr(UnboxUtil::Unbox<P1>(objs[0]));
Expand All @@ -52,13 +52,11 @@ struct gen_lambda
}

template<typename R, typename P1, typename P2>
static std::function<Object_sp(array_list<Object_sp>&&)> get(R(*ptr)(P1, P2))
static auto Generate(R(*ptr)(P1, P2))
{
return [ptr](array_list<Object_sp>&& objs) -> Object_sp {
auto ret = ptr(UnboxUtil::Unbox<P1>(objs[0]), UnboxUtil::Unbox<P2>(objs[1]));
return BoxUtil::Box(ret);
};
return FunctionDelegate<R, P1, P2>(ptr);
}

};

class DataModel : public Object
Expand All @@ -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<Object> 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<ParameterInfo*> infos;
ReflectionBuilder::CreateMethodParameterInfos(AddOne, &infos);
ReflectionBuilder::CreateMethodInfo(StaticType(), "AddOne", true, std::move(infos));
auto lambd = [](array_list<Object_sp>&& objs) -> Object_sp {
auto ret = AddOne(UnboxUtil::Unbox<int32_t>(objs[0]), UnboxUtil::Unbox<int64_t>(objs[1]));
return BoxUtil::Box(ret);
};
gen_lambda::get(AddOne);
}
} __corelib_refl_AddOne_;
};


Expand Down Expand Up @@ -146,8 +122,13 @@ void TestReflection()
assert(value == obj);


MethodInfo* minfo = cltypeof<DataModel>()->GetMethodInfo("AddOne");
assert(minfo->get_parameter_infos().at(0)->GetParamType() == cltypeof<Integer32>());
assert(minfo->get_parameter_infos().at(1)->GetParamType() == cltypeof<Integer64>());
minfo->Invoke(model, {});
MethodInfo* minfo = cltypeof<DataModel>()->GetMethodInfo("Add");
assert(minfo->GetParameterInfos().at(0)->GetParamType() == cltypeof<Integer32>());
assert(minfo->GetParameterInfos().at(1)->GetParamType() == cltypeof<Integer64>());

auto minfoRet1 = minfo->Invoke(nullptr, { mkbox(2), mkbox(3) });
assert(UnboxUtil::Unbox<int>(minfoRet1) == 5);

auto minfoRet2 = cltypeof<DataModel>()->GetMethodInfo("Minus")->Invoke(mksptr(new DataModel), {mkbox(2), mkbox(5)});
assert(UnboxUtil::Unbox<int>(minfoRet2) == -3);
}

0 comments on commit d426f83

Please sign in to comment.