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;
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;
};
}

View File

@ -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>>;

View File

@ -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;
}
};
}

View File

@ -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;
}();
};
}

View File

@ -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();
};
}

View File

@ -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;
}
}

View File

@ -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 };
}
}

View File

@ -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";
}