update refl

This commit is contained in:
ouczbs 2024-04-06 23:50:17 +08:00
parent 2c39b681a3
commit 326f9b10be
6 changed files with 180 additions and 96 deletions

View File

@ -6,16 +6,18 @@ using Ubpa::Name;
using Ubpa::type_name; using Ubpa::type_name;
namespace refl { namespace refl {
class UClass; class UClass;
using Method = void(*)(...);
using Offset = uint32_t;
enum FieldFlag:uint32_t { enum FieldFlag:uint32_t {
FIELD_NONE_FLAG = 0, FIELD_NONE_FLAG = 0,
FIELD_MEMBER_FLAG = 1 << 0, FIELD_MEMBER_FLAG = 1 << 0,
FIELD_ATTRIBUTE_FLAG = 1 << 1, FIELD_ATTRIBUTE_FLAG = 1 << 1,
FIELD_METHOD_FLAG = 1 << 2, FIELD_METHOD_FLAG = 1 << 2,
}; };
struct FieldPtr { struct FieldPtr {
using Data = std::variant< using Data = std::variant<
uint32_t, // offset Offset, // offset
void* // method Method // method
>; >;
Name name; Name name;
const UClass* type; const UClass* type;

View File

@ -1,25 +0,0 @@
#include <string>
namespace refl {
class UClass;
class FieldPtr;
class ObjectView {
public:
const char* ptr;
const UClass* cls;
const FieldPtr* cache{nullptr};
ObjectView(void* ptr, const UClass* cls) : ptr((const char*)ptr), cls(cls){}
public:
template<typename T>
bool Get(const Name& name, T& t);
template<typename T>
bool Set(const Name& name, const T& t);
template<typename ...Args>
bool Invoke(const Name& name, Args... args);
template<typename R, typename ...Args>
bool InvokeRet(const Name& name,R& ret, Args... args);
};
}

View File

@ -8,13 +8,24 @@ namespace refl {
template <class T> template <class T>
concept _ReflCheck_Ctor_NoUClass = _ReflCheck_Ctor<T> && !_ReflCheck_UClass<T>; concept _ReflCheck_Ctor_NoUClass = _ReflCheck_Ctor<T> && !_ReflCheck_UClass<T>;
//主模板只有声明,没有定义,从而使得非特化非法 //类型接口
template<typename T> template<typename T>
struct TypeInfo; struct TypeInfoImpl;
template<_ReflCheck_UClass T> template<_ReflCheck_UClass T>
struct TypeInfo<T> { struct TypeInfoImpl<T> {
using UClass = typename T::UClass; using UClass = typename T::UClass;
inline static UClass StaticClass = UClass::BuildClass(); inline static UClass StaticClass = UClass::BuildClass();
}; };
template<typename T>
struct RealTypeImpl {
using type = std::remove_cv_t<std::remove_reference_t<T>>;
};
template<typename T>
struct RealTypeImpl<T&> {
using type = std::remove_cv_t<T>*;
};
template<typename T>
using TypeInfo = TypeInfoImpl<typename RealTypeImpl<T>::type>;
} }

View File

@ -1,8 +1,14 @@
#pragma once #pragma once
#include "type.h" #include "type.h"
#include "field.h" #include "field.h"
#include "object.h" #include "view.h"
namespace refl { namespace refl {
enum ClassFlag :uint32_t {
CLASS_NONE_FLAG = 0,
CLASS_MEMBER_FLAG = 1 << 0,
CLASS_ATTRIBUTE_FLAG = 1 << 1,
CLASS_METHOD_FLAG = 1 << 2,
};
class UClass{ class UClass{
using enum FieldFlag; using enum FieldFlag;
public: public:
@ -45,6 +51,7 @@ namespace refl {
} }
return false; return false;
} }
public:
//unsafe if called by other, need check class && size //unsafe if called by other, need check class && size
virtual void InitObject(void* ptr)const { virtual void InitObject(void* ptr)const {
memset(ptr, 0, size); memset(ptr, 0, size);
@ -52,30 +59,46 @@ namespace refl {
virtual const FieldPtr* GetField(const Name& name)const { virtual const FieldPtr* GetField(const Name& name)const {
return nullptr; return nullptr;
} }
virtual std::vector<UClass*> GetParams() const {
return{};
}
virtual void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList)const{}
virtual bool ConvertToValue(ArgsView& args)const{
return false;
}
protected: protected:
template<uint32_t offset, typename T,typename U> template<typename T,Offset offset>
FieldPtr MakeMemberField(T U::* ptr, Name name) { FieldPtr MakeMemberField(Name name) {
FieldPtr::Data member = { offset }; FieldPtr::Data member = { offset };
constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_ATTRIBUTE_FLAG; constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_ATTRIBUTE_FLAG;
return { name, &TypeInfo<T>::StaticClass, {member}, flag }; return { name, &TypeInfo<T>::StaticClass, {member}, flag };
} }
template<typename R, typename ...Args> template<typename R, typename ...Args>
FieldPtr MakeMethodField(R (* ptr)(Args...), Name name) { FieldPtr MakeMethodField(R (* ptr)(Args...), Name name) {
FieldPtr::Data member = { *(void**)&ptr }; FieldPtr::Data member = { *(Method*)&ptr};
constexpr uint32_t flag = FIELD_METHOD_FLAG; constexpr uint32_t flag = FIELD_METHOD_FLAG;
return { name, &TypeInfo<decltype(ptr)>::StaticClass, {member},flag }; return { name, &TypeInfo<R(*)(Args...)>::StaticClass, {member},flag };
} }
template<typename T, typename R, typename ...Args> template<typename T, typename R, typename ...Args>
FieldPtr MakeMethodField(R(T::* ptr)(Args...), Name name) { FieldPtr MakeMethodField(R(T::* ptr)(Args...), Name name) {
FieldPtr::Data member = { *(void**)&ptr }; FieldPtr::Data member = { *(Method*)&ptr };
constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_METHOD_FLAG; constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_METHOD_FLAG;
return { name, &TypeInfo<R(*)(Args...)>::StaticClass, {member},flag }; return { name, &TypeInfo<R(*)(const void*, Args...)>::StaticClass, {member},flag };
} }
}; };
template<_ReflCheck_Ctor T> template<_ReflCheck_Ctor T>
class UClass_Auto : public UClass{ class UClass_Auto : public UClass{
public: public:
using UClass::UClass; using UClass::UClass;
bool ConvertToValue(ArgsView& args)const override {
if constexpr (std::is_same<T, int*>::value) {
using RawT = std::remove_pointer_t<T>;
args.val = (void*)*(RawT*)args.val;
args.cls = &TypeInfo<RawT>::StaticClass;
return true;
}
return false;
}
protected: protected:
void InitObject(void* ptr)const override { void InitObject(void* ptr)const override {
constexpr bool is_shallow_copyable = std::is_trivially_copyable<T>::value; constexpr bool is_shallow_copyable = std::is_trivially_copyable<T>::value;
@ -93,17 +116,36 @@ namespace refl {
return cls; return cls;
} }
}; };
template<_ReflCheck_Ctor_NoUClass T> template<_ReflCheck_Ctor_NoUClass T>
struct TypeInfo<T> { struct TypeInfoImpl<T>{
using UClass = UClass_Auto<T>; using UClass = UClass_Auto<T>;
inline static UClass StaticClass = UClass::BuildClass(); inline static UClass StaticClass = UClass::BuildClass();
}; };
template<typename R, typename... Args> template<typename R, typename... Args>
class UMethod_Auto : public UClass { class UMethod_Auto : public UClass {
using UClass::UClass; using UClass::UClass;
using MethodType = R(*)(Args...); using MethodType = R(*)(Args...);
public: public:
std::array<UClass*, sizeof...(Args) + 1> UList; std::array<UClass*, sizeof...(Args) + 1> UList;
std::vector<UClass*> GetParams()const override {
return { UList.data(), UList.data() + UList.size()};
}
void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList)const override {
Call<Args...>(field, ArgsList);
}
protected:
template<typename... Args>
inline void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList)const {
MethodType fptr = (MethodType)std::get<Method>(field.data);
int Indices = 0;
//fptr(ArgsList[1].val, Indices, Indices);
//fptr(std::forward<Args>((Args)Indices), ...);
int a = 1;
a = a + 1;
}
public: public:
static UMethod_Auto<R,Args...> BuildClass() { static UMethod_Auto<R,Args...> BuildClass() {
auto cls = UMethod_Auto<R, Args...>(type_name<MethodType>().View(), sizeof(MethodType)); auto cls = UMethod_Auto<R, Args...>(type_name<MethodType>().View(), sizeof(MethodType));
@ -119,7 +161,7 @@ namespace refl {
}; };
// 函数指针类型的偏特化 // 函数指针类型的偏特化
template<typename R, typename... Args> template<typename R, typename... Args>
struct TypeInfo<R(*)(Args...)> { struct TypeInfoImpl<R(*)(Args...)> {
using UClass = UMethod_Auto<R,Args...>; using UClass = UMethod_Auto<R,Args...>;
inline static UClass StaticClass = UClass::BuildClass(); inline static UClass StaticClass = UClass::BuildClass();
}; };
@ -159,26 +201,36 @@ _cache_set: bool isChild = cache->type->IsChildOf<T>(true);
return false; return false;
} }
template<typename ...Args> template<typename ...Args>
bool ObjectView::Invoke(const Name& name, Args... args) bool ObjectView::Invoke(const Name& name, Args&&... args)
{ {
auto field = cls->GetField(name); auto field = cls->GetField(name);
if (!field) { if (!field) {
return false; return false;
} }
if (field->flag & FIELD_MEMBER_FLAG) { constexpr int inputSize = sizeof...(Args);
using MemberMethodType = void(*)(const void*, Args...); auto params = field->type->GetParams();
MemberMethodType fptr = (MemberMethodType)std::get<void*>(field->data); int paramsSize = params.size();
fptr(ptr, args...); bool member = field->flag & FIELD_MEMBER_FLAG;
if (inputSize + member >= paramsSize) {
return false;
} }
else { std::vector<ArgsView> ArgsList;
using MethodType = void(*)(Args...); ArgsList.reserve(paramsSize);
MethodType fptr = (MethodType)std::get<void*>(field->data); ArgsList.emplace_back();
fptr(args...); if (member) {
ArgsList.emplace_back(ptr, cls );
} }
return true; (..., (ArgsList.emplace_back((void*)&args, &TypeInfo<Args>::StaticClass)));
for (int i = member + 1; i < paramsSize; i++) {
if (ArgsList[i].cls != params[i]) {
ArgsList[i].ConvertTo(params[i]);
}
}
field->type->Call(*field, ArgsList);
return false;
} }
template<typename R, typename ...Args> template<typename R, typename ...Args>
inline bool ObjectView::InvokeRet(const Name& name, R& ret, Args ...args) inline bool ObjectView::InvokeRet(const Name& name, R& ret, Args&& ...args)
{ {
auto field = cls->GetField(name); auto field = cls->GetField(name);
if (!field) { if (!field) {
@ -186,14 +238,23 @@ _cache_set: bool isChild = cache->type->IsChildOf<T>(true);
} }
if (field->flag & FIELD_MEMBER_FLAG) { if (field->flag & FIELD_MEMBER_FLAG) {
using MemberMethodType = R(*)(const void*, Args...); using MemberMethodType = R(*)(const void*, Args...);
MemberMethodType fptr = (MemberMethodType)std::get<void*>(field->data); MemberMethodType fptr = (MemberMethodType)std::get<Method>(field->data);
ret = fptr(ptr, args...); ret = fptr(ptr, std::forward<Args>(args)...);
} }
else { else {
using MethodType = R(*)(Args...); using MethodType = R(*)(Args...);
MethodType fptr = (MethodType)std::get<void*>(field->data); MethodType fptr = (MethodType)std::get<Method>(field->data);
ret = fptr(args...); ret = fptr(std::forward<Args>(args)...);
} }
return true; return true;
} }
bool ArgsView::ConvertTo(UClass* toClass) {
ArgsView args{val};
cls->ConvertToValue(args);
if (args.cls == toClass) {
*this = args;
return true;
}
return false;
}
} }

View File

@ -0,0 +1,32 @@
#include <string>
namespace refl {
class UClass;
class FieldPtr;
class ObjectView {
public:
const char* ptr;
const UClass* cls;
const FieldPtr* cache{nullptr};
ObjectView(const void* ptr, const UClass* cls) : ptr((const char*)ptr), cls(cls){}
public:
template<typename T>
bool Get(const Name& name, T& t);
template<typename T>
bool Set(const Name& name, const T& t);
template<typename ...Args>
bool Invoke(const Name& name, Args&&... args);
template<typename R, typename ...Args>
bool InvokeRet(const Name& name,R& ret, Args&&... args);
};
class ArgsView {
public:
const void* val;
const UClass* cls;
ArgsView(const void* val = nullptr, const UClass* cls = nullptr) : val(val), cls(cls) {}
bool ConvertTo(UClass* toClass);
};
}

View File

@ -15,18 +15,18 @@ struct vec3 : public vec3_parent {
float y = 2; float y = 2;
float z = 3; float z = 3;
string name{ "hellohellohellohellohellohello" }; string name{ "hellohellohellohellohellohello" };
void norm(int x1) { void norm(int x1, int& x2) {
x1 = x * y * z; x2 = x1 * x * y * z * x2;
cout << x1 << "::norm" << endl; cout << x2 << "::norm" << endl;
} }
virtual float norm1(int x1) { virtual float norm1(int x1 = 10) {
cout << x1 << "::norm1" << endl; cout << x1 << "::norm1" << endl;
return x * y *z * x1; return x * y *z * x1;
} }
static void norm2(int x1) { static void norm2(int x1 = 10) {
cout << x1 << "::norm2" << endl; cout << x1 << "::norm2" << endl;
} }
void norm3(int x1) { void norm3(int x1 = 10) {
x1 = x * y * z; x1 = x * y * z;
cout << x1 << "::norm3" << endl; cout << x1 << "::norm3" << endl;
} }
@ -50,41 +50,44 @@ public:
static vec3_UClass BuildClass() { static vec3_UClass BuildClass() {
vec3_UClass cls(type_name<vec3>().View(), sizeof(vec3), &TypeInfo<vec3_parent>::StaticClass); vec3_UClass cls(type_name<vec3>().View(), sizeof(vec3), &TypeInfo<vec3_parent>::StaticClass);
//offsetof(vec3, x) 很坑,相当坑 //offsetof(vec3, x) 很坑,相当坑
cls.FList[0] = cls.MakeMemberField<offsetof(vec3, x)>(&vec3::x, "x"); cls.FList[0] = cls.MakeMemberField<float, offsetof(vec3, x)>("x");
cls.FList[1] = cls.MakeMemberField<offsetof(vec3, y)>(&vec3::y, "y"); cls.FList[1] = cls.MakeMemberField<float, offsetof(vec3, y)>("y");
cls.FList[2] = cls.MakeMemberField<offsetof(vec3, z)>(&vec3::z, "z"); cls.FList[2] = cls.MakeMemberField<float, offsetof(vec3, z)>("z");
cls.FList[3] = cls.MakeMethodField(&vec3::norm, "norm"); cls.FList[3] = cls.MakeMethodField(&vec3::norm, "norm");
cls.FList[4] = cls.MakeMethodField(&vec3::norm1, "norm1"); //cls.FList[4] = cls.MakeMethodField(&vec3::norm1, "norm1");
cls.FList[5] = cls.MakeMethodField(&vec3::norm2, "norm2"); //cls.FList[5] = cls.MakeMethodField(&vec3::norm2, "norm2");
return cls; return cls;
} }
}; };
int main() { template<typename ...Args>
auto& cls = TypeInfo<vec3>::StaticClass; void printt(void* ptr, std::vector<ArgsView>& ArgsList) {
auto ptr1 = &vec3::norm; using MethodType = void (*)(Args...);
auto ptr2 = &vec3::norm1; MethodType fptr = (MethodType)ptr;
auto ptr3 = &vec3::norm2; auto param = ArgsList.begin();
auto ptr4 = &vec3::norm3; auto val1 = (++param)->val;
vec3 v; auto val2 = (++param)->val;
using Any = void*; auto val3 = (++param)->val;
ObjectView pv(&v, &cls); fptr(val1, (int)val2, (int*)(void *)val3);
//using ClassMethod = void(Any::*)(int); //fptr(val1, (int)val2, std::forward<int&>((int&)val3));
using MethodType = void(void*, int); //fptr((++param)->val, (int)(++param)->val, (int&)(++param)->val);
MethodType* ptr_wrap = (MethodType*)*(void**)&ptr1; //fptr(std::forward<Args>(Args(param++->val))...);
pv.Invoke("norm", 10); int x = 1;
ptr_wrap(&v, 10); x = x + 1;
ptr_wrap = (MethodType*)*(void**)&ptr2; }
float x; int main() {
pv.InvokeRet("norm1",x ,10); auto cls = &TypeInfo<vec3>::StaticClass;
ptr_wrap(&v, 10); vec3 v;
ptr_wrap = (MethodType*)*(void**)&ptr3; int x = 1, y = 2;
pv.Invoke("norm2", 10); std::vector<ArgsView> ArgsList;
ptr_wrap(&v, 10); ArgsList.emplace_back();
ptr_wrap = (MethodType*)*(void**)&ptr4; ArgsList.emplace_back(&v);
ptr_wrap(&v, 10); ArgsList.emplace_back((void*)x);
PrintHex8(ptr1); ArgsList.emplace_back(&y);
PrintHex8(ptr2); auto ptr1 = &vec3::norm;
PrintHex8(ptr3); using MethodType = void (*)(void*, int, int*);
PrintHex8(ptr4); MethodType ptr2 = *(MethodType*)&ptr1;
cout << "hello world\n"; ptr2(&v, x , &y);
printt<const void*, int , int*>(*(void**)&ptr1, ArgsList);
//ptr2(x, y);
//cout << "hello world\n";
} }