support refl method default value

This commit is contained in:
ouczbs 2024-04-09 16:31:09 +08:00
parent deba7160c2
commit 1358747979
8 changed files with 233 additions and 84 deletions

View File

@ -6,22 +6,42 @@ using Ubpa::Name;
using Ubpa::type_name; using Ubpa::type_name;
namespace refl { namespace refl {
class UClass; class UClass;
class ArgsView;
using Offset = uint32_t; using Offset = uint32_t;
using Method = void(*)(...); using Method = void(*)(...);
using DefaultMember = const ArgsView (*)();
using DefaultMethod = std::pair<ArgsView*, int>(*)();
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,
FIELD_METHOD_VALUE_FLAG = 1 << 3
}; };
struct FieldPtr { struct FieldPtr {
using Data = std::variant< union Data
Offset, // offset {
Method // method Offset offset;
>; Method method;
Data() : method(nullptr) {}
Data(Offset& offset) : offset(offset) {}
Data(Method& method) : method(method) {}
};
union Default {
DefaultMember member;
DefaultMethod method;
Default(): method(nullptr) {}
Default(DefaultMember& member) : member(member) {}
Default(DefaultMethod& method) : method(method) {}
};
Name name; Name name;
const UClass* type; const UClass* type;
Data data; Data data;
Default value;
uint32_t flag; uint32_t flag;
}; };
} }

View File

@ -4,20 +4,13 @@ namespace refl {
template <class T> template <class T>
concept _ReflCheck_Ctor = requires { T(); }; concept _ReflCheck_Ctor = requires { T(); };
template <class T> template <class T>
concept _ReflCheck_UClass = requires{{T::BuildClass()} -> std::same_as<typename T::MyUClass>; }; concept _ReflCheck_UClass = requires(typename T::MyUClass& cls) { T::BuildClass(cls); } ;
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 TypeInfoImpl; struct TypeInfoImpl;
template<_ReflCheck_UClass T>
struct TypeInfoImpl<T> {
using MyUClass = typename T::MyUClass;
inline static MyUClass StaticClass = T::BuildClass();
};
template<typename T> template<typename T>
struct RealTypeImpl { struct RealTypeImpl {
using type = std::remove_cv_t<std::remove_reference_t<T>>; using type = std::remove_cv_t<std::remove_reference_t<T>>;

View File

@ -5,8 +5,6 @@
namespace refl { namespace refl {
struct vtable_uclass struct vtable_uclass
{ {
//object
void (*InitObject)(void*);
//class //class
const FieldPtr* (*GetField)(const UClass*, const Name&, bool); const FieldPtr* (*GetField)(const UClass*, const Name&, bool);
//function //function
@ -14,6 +12,10 @@ namespace refl {
//function //function
void (*Call)(const FieldPtr&, std::vector<ArgsView>&); void (*Call)(const FieldPtr&, std::vector<ArgsView>&);
//object
void (*InitObject)(void*);
void (*CopyObject)(void*, const void*);
void (*DestObject)(void*);
}; };
class UClass{ class UClass{
using enum FieldFlag; using enum FieldFlag;
@ -70,20 +72,6 @@ namespace refl {
return false; return false;
} }
public: public:
template<_ReflCheck_Ctor T>
static void InitObject(void* ptr) {
T obj{};
std::construct_at((T*)ptr, obj);
}
//unsafe if called by other, need check class && size
void InitObject(void* ptr)const {
if (vtable.InitObject) {
vtable.InitObject(ptr);
}
else {
memset(ptr, 0, size);
}
}
const FieldPtr* GetField(const Name& name, bool isMethod)const { const FieldPtr* GetField(const Name& name, bool isMethod)const {
if (vtable.GetField) { if (vtable.GetField) {
return vtable.GetField(this, name, isMethod); return vtable.GetField(this, name, isMethod);
@ -101,24 +89,36 @@ namespace refl {
return vtable.Call(field, ArgsList); return vtable.Call(field, ArgsList);
} }
} }
void InitObject(void* ptr)const {
if (vtable.InitObject) {
vtable.InitObject(ptr);
}
else {
memset(ptr, 0, size);
}
}
void CopyObject(void* dst, const void* src)const {
if (vtable.CopyObject) {
vtable.CopyObject(dst, src);
}
else {
memcpy(dst, src, size);
}
}
void DestObject(void* ptr)const {
if (vtable.DestObject) {
vtable.DestObject(ptr);
}
}
public: public:
template<Offset offset> template<_ReflCheck_Ctor T>
constexpr static FieldPtr MakeMemberField(Name name, const UClass* cls) { static void InitObject(void* ptr) {
FieldPtr::Data member = { offset }; T obj{};
constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_ATTRIBUTE_FLAG; std::construct_at((T*)ptr, obj);
return { name, cls, {member}, flag };
} }
template<typename R, typename ...Args> template<typename T>
static FieldPtr MakeMethodField(R (* ptr)(Args...), Name name) { static void CopyObject(void* dst, const void* src) {
FieldPtr::Data member = { *(Method*)&ptr}; *(T*)dst = *(T*)src;
constexpr uint32_t flag = FIELD_METHOD_FLAG;
return { name, &TypeInfo<R(*)(typename RealTypeImpl<Args>::type...)>::StaticClass, {member},flag };
}
template<typename T, typename R, typename ...Args>
static FieldPtr MakeMethodField(R(T::* ptr)(Args...), Name name) {
FieldPtr::Data member = { *(Method*)&ptr };
constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_METHOD_FLAG;
return { name, &TypeInfo<R(*)(const void*, typename RealTypeImpl<Args>::type...)>::StaticClass, {member},flag };
} }
}; };
} }

View File

@ -5,12 +5,13 @@ namespace refl {
class UClass_Auto : public UClass { class UClass_Auto : public UClass {
public: public:
using UClass::UClass; using UClass::UClass;
using UClassType = UClass_Auto<T>; using MyUClass = UClass_Auto<T>;
public: public:
constexpr static UClassType BuildClass() { constexpr static MyUClass BuildClass() {
UClassType cls(type_name<T>().View(), sizeof(T)); MyUClass cls(type_name<T>().View(), sizeof(T));
if constexpr (!std::is_trivially_copyable_v<T>) { if constexpr (!std::is_trivially_copyable_v<T>) {
cls.vtable.InitObject = &UClass::InitObject<T>; cls.vtable.InitObject = &MyUClass::InitObject<T>;
cls.vtable.CopyObject = &MyUClass::CopyObject<T>;
} }
return cls; return cls;
} }
@ -25,22 +26,22 @@ namespace refl {
class UMethod_Auto : public UClass { class UMethod_Auto : public UClass {
using UClass::UClass; using UClass::UClass;
using MethodType = R(*)(Args...); using MethodType = R(*)(Args...);
using UClassType = UMethod_Auto<R, Args...>; using MyUClass = UMethod_Auto<R, Args...>;
public: public:
std::array<const UClass*, sizeof...(Args) + 1> UList{}; std::array<const UClass*, sizeof...(Args) + 1> UList{};
static std::vector<const UClass*> GetParams(const UClass* cls) { static std::vector<const UClass*> GetParams(const UClass* cls) {
auto& UList = static_cast<const UClassType*>(cls)->UList; auto& UList = static_cast<const MyUClass*>(cls)->UList;
return { UList.data(), UList.data() + UList.size() }; return { UList.data(), UList.data() + UList.size() };
} }
static void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList) { static void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList) {
if constexpr (std::is_same_v<R, void>) { if constexpr (std::is_same_v<R, void>) {
MethodType fptr = (MethodType)std::get<Method>(field.data); MethodType fptr = (MethodType)field.data.method;
auto param = ArgsList.rbegin(); auto param = ArgsList.rbegin();
fptr(param++->cast_to<Args>()...); fptr(param++->cast_to<Args>()...);
} }
else { else {
MethodType fptr = (MethodType)std::get<Method>(field.data); MethodType fptr = (MethodType)field.data.method;
auto param = ArgsList.rbegin(); auto param = ArgsList.rbegin();
auto ret = ArgsList.begin(); auto ret = ArgsList.begin();
if (ret->cls == &TypeInfo<R>::StaticClass) { if (ret->cls == &TypeInfo<R>::StaticClass) {
@ -63,10 +64,10 @@ namespace refl {
} }
public: public:
//为了简化判断cls 对象 统统指向 T* //为了简化判断cls 对象 统统指向 T*
constexpr static UClassType BuildClass() { constexpr static MyUClass BuildClass() {
UClassType cls(type_name<MethodType>().View(), sizeof(MethodType)); MyUClass cls(type_name<MethodType>().View(), sizeof(MethodType));
cls.vtable.GetParams = &UClassType::GetParams; cls.vtable.GetParams = &MyUClass::GetParams;
cls.vtable.Call = &UClassType::Call; cls.vtable.Call = &MyUClass::Call;
cls.BuildUList(); cls.BuildUList();
return cls; return cls;
} }
@ -93,9 +94,12 @@ namespace refl {
} }
return nullptr; return nullptr;
} }
/*
void BuildClass() { void BuildClass() {
FList.shrink_to_fit();//缩减容量FList大小不再改变了
vtable.GetField = &UClass_Custom::GetField; vtable.GetField = &UClass_Custom::GetField;
} }
*/
}; };
//基础类型的偏特化 //基础类型的偏特化
template<_ReflCheck_Ctor_NoUClass T> template<_ReflCheck_Ctor_NoUClass T>
@ -110,4 +114,28 @@ namespace refl {
using UClass = UMethod_Auto<R, Args...>; using UClass = UMethod_Auto<R, Args...>;
inline constexpr static UClass StaticClass = UClass::BuildClass(); inline constexpr static UClass StaticClass = UClass::BuildClass();
}; };
template<_ReflCheck_UClass T>
struct TypeInfoImpl<T> {
using MyUClass = typename T::MyUClass;
inline static MyUClass StaticClass = []()->MyUClass {
MyUClass cls(type_name<T>().View(), sizeof(T));
T::BuildClass(cls);
auto& vtable = cls.vtable;
if (!vtable.GetField) {
vtable.GetField = &MyUClass::GetField;
}
if constexpr (!std::is_trivially_copyable_v<T>) {
if (!vtable.InitObject) {
//这里一定会创建一个InitObject<T> 模板函数,如何优化
vtable.InitObject = &UClass::InitObject<T>;
}
if (!vtable.CopyObject) {
//这里一定会创建一个CopyObject<T> 模板函数,如何优化
vtable.CopyObject = &UClass::CopyObject<T>;
}
}
return cls;
}();
};
} }

View File

@ -26,14 +26,22 @@ namespace refl {
ObjectView Parent(); ObjectView Parent();
}; };
class ArgsView { //生命周期短,适用于传参,不建议保存数据
//这里类型丢失了呀,存入的都是指针数据
struct ArgsView {
public: public:
const void* val; const void* val;
const UClass* cls; const UClass* cls;
ArgsView(const void* val = nullptr, const UClass* cls = nullptr) : val(val), cls(cls) {} ArgsView(const void* val = nullptr, const UClass* cls = nullptr) : val(val), cls(cls) {}
//右值=>右值压入栈caller入栈地址
//左值=>caller变量地址
template<typename T> template<typename T>
ArgsView(T&& v): val(&v), cls(&TypeInfo<typename std::remove_reference_t<T>*>::StaticClass){} ArgsView(T&& v): val(&v), cls(&TypeInfo<typename std::remove_reference_t<T>*>::StaticClass){
if constexpr (std::is_same_v<std::remove_reference_t<T>, ArgsView>) {
val = v.val;
cls = v.cls;
}
}
template<typename T> template<typename T>
constexpr inline T cast_to() { constexpr inline T cast_to() {
if constexpr (std::is_pointer_v<T>) { if constexpr (std::is_pointer_v<T>) {
@ -48,4 +56,17 @@ namespace refl {
} }
bool ConvertTo(const UClass* toClass); bool ConvertTo(const UClass* toClass);
}; };
//存入的是真实的数据类型,type用于拷贝数据
struct ArgsValue : public ArgsView {
const UClass* type;
template<typename T>
ArgsValue(T&& t) : ArgsView(t), type(&TypeInfo<T>::StaticClass){}
};
struct ArgsValueList{
void* data{ nullptr };
ArgsView* ptr{nullptr};
int num{ 0 };
ArgsValueList(const std::vector<ArgsValue>& args);
~ArgsValueList();
};
} }

View File

@ -7,7 +7,7 @@ namespace refl {
if (cache && cache->name == name) { if (cache && cache->name == name) {
_cache_get: bool isChild = cache->type->IsChildOf<T>(true); _cache_get: bool isChild = cache->type->IsChildOf<T>(true);
if (isChild) { if (isChild) {
t = *(T*)(ptr + std::get<uint32_t>(cache->data)); t = *(T*)(ptr + cache->data.offset);
} }
return isChild; return isChild;
} }
@ -25,10 +25,9 @@ namespace refl {
inline bool ObjectView::Set(const Name& name, const T& t) inline bool ObjectView::Set(const Name& name, const T& t)
{ {
if (cache && cache->name == name) { if (cache && cache->name == name) {
_cache_set: bool isChild = cache->type->IsChildOf<T>(true); _cache_set: bool isChild = cache->type->IsChildOf<T>(true);
if (isChild) { if (isChild) {
*(T*)(ptr + std::get<uint32_t>(cache->data)) = t; *(T*)(ptr + cache->data.offset) = t;
} }
return isChild; return isChild;
} }
@ -55,17 +54,33 @@ namespace refl {
constexpr int inputSize = sizeof...(Args); constexpr int inputSize = sizeof...(Args);
auto params = field->type->GetParams(); auto params = field->type->GetParams();
int paramsSize = params.size(); int paramsSize = params.size();
bool member = field->flag & FIELD_MEMBER_FLAG;
if (inputSize + member >= paramsSize) {
return false;
}
std::vector<ArgsView> ArgsList; std::vector<ArgsView> ArgsList;
ArgsList.reserve(paramsSize); ArgsList.reserve(paramsSize);
ArgsList.emplace_back(); ArgsList.emplace_back();
bool member = field->flag & FIELD_MEMBER_FLAG;
if (member) { if (member) {
ArgsList.emplace_back(ptr, &TypeInfo<const void*>::StaticClass); ArgsList.emplace_back(ptr, &TypeInfo<const void*>::StaticClass);
} }
(..., (ArgsList.emplace_back(args))); (..., (ArgsList.emplace_back(args)));
int argsSize = ArgsList.size();
if (argsSize < paramsSize && field->flag & FIELD_METHOD_VALUE_FLAG) {
auto [argsPtr, valueSize] = field->value.method();
if (argsSize + valueSize >= paramsSize) {
for (int i = valueSize + argsSize - paramsSize; i < valueSize; i++) {
ArgsList.push_back(*(argsPtr + i));
}
argsSize = paramsSize;
}
}
if (argsSize < paramsSize) {
return false;
}
for (int i = member + 1; i < paramsSize; i++) { for (int i = member + 1; i < paramsSize; i++) {
if (ArgsList[i].cls != params[i] && !ArgsList[i].ConvertTo(params[i])) { if (ArgsList[i].cls != params[i] && !ArgsList[i].ConvertTo(params[i])) {
return false; return false;
@ -123,4 +138,35 @@ namespace refl {
} }
return false; return false;
} }
ArgsValueList::ArgsValueList(const std::vector<ArgsValue>& args) {
num = args.size();
int size = num * sizeof(ArgsView);
for (auto& arg : args) {
size += arg.cls->size;
}
data = (void*)malloc(size);
ptr = (ArgsView*)data;
char* pData = ((char*)data) + num * sizeof(ArgsView);
for (auto& arg : args) {
arg.type->InitObject(pData);
arg.type->CopyObject(pData, arg.val);
ptr->cls = arg.cls;
ptr->val = pData;
ptr++;
pData += arg.cls->size;
}
ptr = (ArgsView*)data;
}
inline ArgsValueList::~ArgsValueList()
{
if (num == 0 || !data) {
return;
}
for (int i = 0; i < num; i++) {
ptr->cls->DestObject((void*)ptr->val);
}
free(data);
num = 0;
data = nullptr;
}
} }

View File

@ -1,2 +1,41 @@
#include "detail/uclass.inl" #include "detail/uclass.inl"
#include "detail/view.inl" #include "detail/view.inl"
namespace refl {
/* 成员变量需要定义默认值吗那为什么不在initObjec里初始化?*/
template<typename T, typename Obj>
static FieldPtr MakeMemberField(T Obj::* ptr, Name name) {
FieldPtr::Default value;
Offset offset = reinterpret_cast<std::size_t>(&(reinterpret_cast<const Obj*>(0)->*ptr));
FieldPtr::Data member = { offset };
constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_ATTRIBUTE_FLAG;
return { name, &TypeInfo<T>::StaticClass, member, value, flag };
}
template<typename R, typename ...Args>
static FieldPtr MakeMethodField(R(*ptr)(Args...), Name name, const std::vector<ArgsValue>& args = {}) {
uint32_t flag = FIELD_METHOD_FLAG;
FieldPtr::Default value;
if (args.size() > 0) {
flag |= FIELD_METHOD_VALUE_FLAG;
static const ArgsValueList argsValue(args);
value.method = []() ->std::pair<ArgsView*, int> {
return { argsValue.ptr , argsValue.num };
};
}
FieldPtr::Data method = { *(Method*)&ptr };
return { name, &TypeInfo<R(*)(typename RealTypeImpl<Args>::type...)>::StaticClass, method, value, flag };
}
template<typename T, typename R, typename ...Args>
static FieldPtr MakeMethodField(R(T::* ptr)(Args...), Name name, const std::vector<ArgsValue>& args = {}) {
uint32_t flag = FIELD_MEMBER_FLAG | FIELD_METHOD_FLAG;
FieldPtr::Default value;
if (args.size() > 0) {
flag |= FIELD_METHOD_VALUE_FLAG;
static const ArgsValueList argsValue(args);
value.method = []() ->std::pair<ArgsView*, int> {
return { argsValue.ptr , argsValue.num };
};
}
FieldPtr::Data method = { *(Method*)&ptr };
return { name, &TypeInfo<R(*)(const void*, typename RealTypeImpl<Args>::type...)>::StaticClass, method, value,flag };
}
}

View File

@ -33,27 +33,29 @@ struct vec3 : public vec3_parent {
cout << x1 << "::norm3" << endl; cout << x1 << "::norm3" << endl;
} }
using MyUClass = UClass_Custom; using MyUClass = UClass_Custom;
static MyUClass BuildClass() { static void BuildClass(MyUClass& cls) {
MyUClass cls(type_name<vec3>().View(), sizeof(vec3), &TypeInfo<vec3_parent>::StaticClass); cls.parent = &TypeInfo<vec3_parent>::StaticClass;
auto& FList = cls.FList; cls.AttrNum = 3;
FList.reserve(6); cls.FList = {
FList.push_back(cls.MakeMemberField<offsetof(vec3, x)>("x", &TypeInfo<float>::StaticClass)); MakeMemberField(&vec3::x, "x"),
FList.push_back(cls.MakeMemberField<offsetof(vec3, y)>("y", &TypeInfo<float>::StaticClass)); MakeMemberField(&vec3::y, "y"),
FList.push_back(cls.MakeMemberField<offsetof(vec3, z)>("z", &TypeInfo<float>::StaticClass)); MakeMemberField(&vec3::z, "z"),
cls.AttrNum = FList.size(); MakeMethodField(&vec3::norm, "norm", {8, 9}),
FList.push_back(cls.MakeMethodField(&vec3::norm, "norm")); MakeMethodField(&vec3::norm1, "norm1",{2})
FList.push_back(cls.MakeMethodField(&vec3::norm, "norm1")); };
cls.vtable.InitObject = &UClass::InitObject<vec3>;
cls.BuildClass();
return cls;
} }
}; };
int main() { int main() {
auto cls = &TypeInfo<vec3>::StaticClass; auto cls = &TypeInfo<vec3>::StaticClass;
int x = 100, y = 2; int x = 2, y = 3;
auto ov = cls->New(); auto ov = cls->New();
ov.Invoke("norm", x);
ov.Invoke("norm", x);
ov.Invoke("norm", x, y); ov.Invoke("norm", x, y);
ov.Invoke("norm1", y);
vec3* v = (vec3*)ov.ptr; vec3* v = (vec3*)ov.ptr;
v->norm1(y);
ov.Invoke("norm1", y);
delete v; delete v;
cout << "hello world\n"; cout << "hello world\n";
} }