support refl method default value
This commit is contained in:
parent
deba7160c2
commit
1358747979
36
engine/3rdparty/zlib/include/refl/detail/field.h
vendored
36
engine/3rdparty/zlib/include/refl/detail/field.h
vendored
@ -6,22 +6,42 @@ using Ubpa::Name;
|
||||
using Ubpa::type_name;
|
||||
namespace refl {
|
||||
class UClass;
|
||||
class ArgsView;
|
||||
|
||||
using Offset = uint32_t;
|
||||
using Method = void(*)(...);
|
||||
|
||||
using DefaultMember = const ArgsView (*)();
|
||||
using DefaultMethod = std::pair<ArgsView*, int>(*)();
|
||||
|
||||
enum FieldFlag:uint32_t {
|
||||
FIELD_NONE_FLAG = 0,
|
||||
FIELD_MEMBER_FLAG = 1 << 0,
|
||||
FIELD_ATTRIBUTE_FLAG = 1 << 1,
|
||||
FIELD_METHOD_FLAG = 1 << 2,
|
||||
FIELD_NONE_FLAG = 0,
|
||||
FIELD_MEMBER_FLAG = 1 << 0,
|
||||
FIELD_ATTRIBUTE_FLAG = 1 << 1,
|
||||
FIELD_METHOD_FLAG = 1 << 2,
|
||||
FIELD_METHOD_VALUE_FLAG = 1 << 3
|
||||
};
|
||||
struct FieldPtr {
|
||||
using Data = std::variant<
|
||||
Offset, // offset
|
||||
Method // method
|
||||
>;
|
||||
union Data
|
||||
{
|
||||
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;
|
||||
const UClass* type;
|
||||
Data data;
|
||||
Default value;
|
||||
uint32_t flag;
|
||||
};
|
||||
|
||||
}
|
||||
@ -4,20 +4,13 @@ namespace refl {
|
||||
template <class T>
|
||||
concept _ReflCheck_Ctor = requires { 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>
|
||||
concept _ReflCheck_Ctor_NoUClass = _ReflCheck_Ctor<T> && !_ReflCheck_UClass<T>;
|
||||
|
||||
//类型接口
|
||||
template<typename T>
|
||||
struct TypeInfoImpl;
|
||||
|
||||
template<_ReflCheck_UClass T>
|
||||
struct TypeInfoImpl<T> {
|
||||
using MyUClass = typename T::MyUClass;
|
||||
inline static MyUClass StaticClass = T::BuildClass();
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct RealTypeImpl {
|
||||
using type = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
|
||||
@ -5,8 +5,6 @@
|
||||
namespace refl {
|
||||
struct vtable_uclass
|
||||
{
|
||||
//object
|
||||
void (*InitObject)(void*);
|
||||
//class
|
||||
const FieldPtr* (*GetField)(const UClass*, const Name&, bool);
|
||||
//function
|
||||
@ -14,6 +12,10 @@ namespace refl {
|
||||
//function
|
||||
void (*Call)(const FieldPtr&, std::vector<ArgsView>&);
|
||||
|
||||
//object
|
||||
void (*InitObject)(void*);
|
||||
void (*CopyObject)(void*, const void*);
|
||||
void (*DestObject)(void*);
|
||||
};
|
||||
class UClass{
|
||||
using enum FieldFlag;
|
||||
@ -70,20 +72,6 @@ namespace refl {
|
||||
return false;
|
||||
}
|
||||
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 {
|
||||
if (vtable.GetField) {
|
||||
return vtable.GetField(this, name, isMethod);
|
||||
@ -101,24 +89,36 @@ namespace refl {
|
||||
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:
|
||||
template<Offset offset>
|
||||
constexpr static FieldPtr MakeMemberField(Name name, const UClass* cls) {
|
||||
FieldPtr::Data member = { offset };
|
||||
constexpr uint32_t flag = FIELD_MEMBER_FLAG | FIELD_ATTRIBUTE_FLAG;
|
||||
return { name, cls, {member}, flag };
|
||||
template<_ReflCheck_Ctor T>
|
||||
static void InitObject(void* ptr) {
|
||||
T obj{};
|
||||
std::construct_at((T*)ptr, obj);
|
||||
}
|
||||
template<typename R, typename ...Args>
|
||||
static FieldPtr MakeMethodField(R (* ptr)(Args...), Name name) {
|
||||
FieldPtr::Data member = { *(Method*)&ptr};
|
||||
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 };
|
||||
template<typename T>
|
||||
static void CopyObject(void* dst, const void* src) {
|
||||
*(T*)dst = *(T*)src;
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -5,12 +5,13 @@ namespace refl {
|
||||
class UClass_Auto : public UClass {
|
||||
public:
|
||||
using UClass::UClass;
|
||||
using UClassType = UClass_Auto<T>;
|
||||
using MyUClass = UClass_Auto<T>;
|
||||
public:
|
||||
constexpr static UClassType BuildClass() {
|
||||
UClassType cls(type_name<T>().View(), sizeof(T));
|
||||
constexpr static MyUClass BuildClass() {
|
||||
MyUClass cls(type_name<T>().View(), sizeof(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;
|
||||
}
|
||||
@ -25,22 +26,22 @@ namespace refl {
|
||||
class UMethod_Auto : public UClass {
|
||||
using UClass::UClass;
|
||||
using MethodType = R(*)(Args...);
|
||||
using UClassType = UMethod_Auto<R, Args...>;
|
||||
using MyUClass = UMethod_Auto<R, Args...>;
|
||||
public:
|
||||
std::array<const UClass*, sizeof...(Args) + 1> UList{};
|
||||
|
||||
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() };
|
||||
}
|
||||
static void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList) {
|
||||
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();
|
||||
fptr(param++->cast_to<Args>()...);
|
||||
}
|
||||
else {
|
||||
MethodType fptr = (MethodType)std::get<Method>(field.data);
|
||||
MethodType fptr = (MethodType)field.data.method;
|
||||
auto param = ArgsList.rbegin();
|
||||
auto ret = ArgsList.begin();
|
||||
if (ret->cls == &TypeInfo<R>::StaticClass) {
|
||||
@ -63,10 +64,10 @@ namespace refl {
|
||||
}
|
||||
public:
|
||||
//为了简化判断,cls 对象 统统指向 T*
|
||||
constexpr static UClassType BuildClass() {
|
||||
UClassType cls(type_name<MethodType>().View(), sizeof(MethodType));
|
||||
cls.vtable.GetParams = &UClassType::GetParams;
|
||||
cls.vtable.Call = &UClassType::Call;
|
||||
constexpr static MyUClass BuildClass() {
|
||||
MyUClass cls(type_name<MethodType>().View(), sizeof(MethodType));
|
||||
cls.vtable.GetParams = &MyUClass::GetParams;
|
||||
cls.vtable.Call = &MyUClass::Call;
|
||||
cls.BuildUList();
|
||||
return cls;
|
||||
}
|
||||
@ -93,9 +94,12 @@ namespace refl {
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
/*
|
||||
void BuildClass() {
|
||||
FList.shrink_to_fit();//缩减容量,FList大小不再改变了
|
||||
vtable.GetField = &UClass_Custom::GetField;
|
||||
}
|
||||
*/
|
||||
};
|
||||
//基础类型的偏特化
|
||||
template<_ReflCheck_Ctor_NoUClass T>
|
||||
@ -110,4 +114,28 @@ namespace refl {
|
||||
using UClass = UMethod_Auto<R, Args...>;
|
||||
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;
|
||||
}();
|
||||
};
|
||||
}
|
||||
27
engine/3rdparty/zlib/include/refl/detail/view.h
vendored
27
engine/3rdparty/zlib/include/refl/detail/view.h
vendored
@ -26,14 +26,22 @@ namespace refl {
|
||||
|
||||
ObjectView Parent();
|
||||
};
|
||||
class ArgsView {
|
||||
//生命周期短,适用于传参,不建议保存数据
|
||||
//这里类型丢失了呀,存入的都是指针数据
|
||||
struct ArgsView {
|
||||
public:
|
||||
const void* val;
|
||||
const UClass* cls;
|
||||
ArgsView(const void* val = nullptr, const UClass* cls = nullptr) : val(val), cls(cls) {}
|
||||
//右值=>右值压入栈,caller入栈地址
|
||||
//左值=>caller变量地址
|
||||
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>
|
||||
constexpr inline T cast_to() {
|
||||
if constexpr (std::is_pointer_v<T>) {
|
||||
@ -48,4 +56,17 @@ namespace refl {
|
||||
}
|
||||
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();
|
||||
};
|
||||
}
|
||||
@ -7,7 +7,7 @@ namespace refl {
|
||||
if (cache && cache->name == name) {
|
||||
_cache_get: bool isChild = cache->type->IsChildOf<T>(true);
|
||||
if (isChild) {
|
||||
t = *(T*)(ptr + std::get<uint32_t>(cache->data));
|
||||
t = *(T*)(ptr + cache->data.offset);
|
||||
}
|
||||
return isChild;
|
||||
}
|
||||
@ -25,10 +25,9 @@ namespace refl {
|
||||
inline bool ObjectView::Set(const Name& name, const T& t)
|
||||
{
|
||||
if (cache && cache->name == name) {
|
||||
|
||||
_cache_set: bool isChild = cache->type->IsChildOf<T>(true);
|
||||
if (isChild) {
|
||||
*(T*)(ptr + std::get<uint32_t>(cache->data)) = t;
|
||||
*(T*)(ptr + cache->data.offset) = t;
|
||||
}
|
||||
return isChild;
|
||||
}
|
||||
@ -55,17 +54,33 @@ namespace refl {
|
||||
constexpr int inputSize = sizeof...(Args);
|
||||
auto params = field->type->GetParams();
|
||||
int paramsSize = params.size();
|
||||
bool member = field->flag & FIELD_MEMBER_FLAG;
|
||||
if (inputSize + member >= paramsSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<ArgsView> ArgsList;
|
||||
ArgsList.reserve(paramsSize);
|
||||
ArgsList.emplace_back();
|
||||
|
||||
bool member = field->flag & FIELD_MEMBER_FLAG;
|
||||
if (member) {
|
||||
ArgsList.emplace_back(ptr, &TypeInfo<const void*>::StaticClass);
|
||||
}
|
||||
(..., (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++) {
|
||||
if (ArgsList[i].cls != params[i] && !ArgsList[i].ConvertTo(params[i])) {
|
||||
return false;
|
||||
@ -123,4 +138,35 @@ namespace refl {
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
39
engine/3rdparty/zlib/include/refl/refl.h
vendored
39
engine/3rdparty/zlib/include/refl/refl.h
vendored
@ -1,2 +1,41 @@
|
||||
#include "detail/uclass.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 };
|
||||
}
|
||||
}
|
||||
30
engine/3rdparty/zlib/test/refl_01.cpp
vendored
30
engine/3rdparty/zlib/test/refl_01.cpp
vendored
@ -33,27 +33,29 @@ struct vec3 : public vec3_parent {
|
||||
cout << x1 << "::norm3" << endl;
|
||||
}
|
||||
using MyUClass = UClass_Custom;
|
||||
static MyUClass BuildClass() {
|
||||
MyUClass cls(type_name<vec3>().View(), sizeof(vec3), &TypeInfo<vec3_parent>::StaticClass);
|
||||
auto& FList = cls.FList;
|
||||
FList.reserve(6);
|
||||
FList.push_back(cls.MakeMemberField<offsetof(vec3, x)>("x", &TypeInfo<float>::StaticClass));
|
||||
FList.push_back(cls.MakeMemberField<offsetof(vec3, y)>("y", &TypeInfo<float>::StaticClass));
|
||||
FList.push_back(cls.MakeMemberField<offsetof(vec3, z)>("z", &TypeInfo<float>::StaticClass));
|
||||
cls.AttrNum = FList.size();
|
||||
FList.push_back(cls.MakeMethodField(&vec3::norm, "norm"));
|
||||
FList.push_back(cls.MakeMethodField(&vec3::norm, "norm1"));
|
||||
cls.vtable.InitObject = &UClass::InitObject<vec3>;
|
||||
cls.BuildClass();
|
||||
return cls;
|
||||
static void BuildClass(MyUClass& cls) {
|
||||
cls.parent = &TypeInfo<vec3_parent>::StaticClass;
|
||||
cls.AttrNum = 3;
|
||||
cls.FList = {
|
||||
MakeMemberField(&vec3::x, "x"),
|
||||
MakeMemberField(&vec3::y, "y"),
|
||||
MakeMemberField(&vec3::z, "z"),
|
||||
MakeMethodField(&vec3::norm, "norm", {8, 9}),
|
||||
MakeMethodField(&vec3::norm1, "norm1",{2})
|
||||
};
|
||||
}
|
||||
};
|
||||
int main() {
|
||||
auto cls = &TypeInfo<vec3>::StaticClass;
|
||||
int x = 100, y = 2;
|
||||
int x = 2, y = 3;
|
||||
auto ov = cls->New();
|
||||
ov.Invoke("norm", x);
|
||||
ov.Invoke("norm", x);
|
||||
ov.Invoke("norm", x, y);
|
||||
ov.Invoke("norm1", y);
|
||||
vec3* v = (vec3*)ov.ptr;
|
||||
v->norm1(y);
|
||||
ov.Invoke("norm1", y);
|
||||
delete v;
|
||||
cout << "hello world\n";
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user