update refl invoke

This commit is contained in:
ouczbs 2024-04-07 21:15:34 +08:00
parent 326f9b10be
commit c6ca4f12ec
4 changed files with 191 additions and 111 deletions

View File

@ -6,8 +6,8 @@ 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; using Offset = uint32_t;
using Method = void(*)(...);
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,
@ -16,8 +16,8 @@ namespace refl {
}; };
struct FieldPtr { struct FieldPtr {
using Data = std::variant< using Data = std::variant<
Offset, // offset Offset, // offset
Method // method Method // method
>; >;
Name name; Name name;
const UClass* type; const UClass* type;

View File

@ -3,21 +3,16 @@
#include "field.h" #include "field.h"
#include "view.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:
Name name; Name name;
uint32_t size; uint32_t size;
UClass* parent; //uint32_t flag;
const UClass* parent;
public: public:
constexpr UClass(Name name, uint32_t size, UClass* parent = nullptr) constexpr UClass(std::string_view name, uint32_t size, const UClass* parent = nullptr)
:name(name),size(size), parent(parent){} :name(name), size(size), parent(parent){}
ObjectView New(void* ptr = nullptr) const{ ObjectView New(void* ptr = nullptr) const{
if (ptr == nullptr) { if (ptr == nullptr) {
ptr = malloc(size); ptr = malloc(size);
@ -36,6 +31,16 @@ namespace refl {
InitObject(ptr); InitObject(ptr);
return ptr; return ptr;
} }
bool IsChildOf(const UClass* cls) const {
const UClass* _parent = parent;
while (_parent != nullptr) {
if (_parent == cls) {
return true;
}
_parent = _parent->parent;
}
return false;
}
template<typename T> template<typename T>
bool IsChildOf(bool bthis = false) const { bool IsChildOf(bool bthis = false) const {
constexpr UClass* cls = &TypeInfo<T>::StaticClass; constexpr UClass* cls = &TypeInfo<T>::StaticClass;
@ -56,53 +61,40 @@ namespace refl {
virtual void InitObject(void* ptr)const { virtual void InitObject(void* ptr)const {
memset(ptr, 0, size); memset(ptr, 0, size);
} }
virtual const FieldPtr* GetField(const Name& name)const { virtual const FieldPtr* GetField(const Name& name, bool isMethod)const {
return nullptr; return nullptr;
} }
virtual std::vector<UClass*> GetParams() const { virtual std::vector<const UClass*> GetParams() const {
return{}; return{};
} }
virtual void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList)const{} virtual void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList)const{}
virtual bool ConvertToValue(ArgsView& args)const{
return false;
}
protected: protected:
template<typename T,Offset offset> template<Offset offset>
FieldPtr MakeMemberField(Name name) { FieldPtr MakeMemberField(Name name, const UClass* cls) {
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, cls, {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 = { *(Method*)&ptr}; FieldPtr::Data member = { *(Method*)&ptr};
constexpr uint32_t flag = FIELD_METHOD_FLAG; constexpr uint32_t flag = FIELD_METHOD_FLAG;
return { name, &TypeInfo<R(*)(Args...)>::StaticClass, {member},flag }; return { name, &TypeInfo<R(*)(typename RealTypeImpl<Args>::type...)>::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 = { *(Method*)&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(*)(const void*, Args...)>::StaticClass, {member},flag }; return { name, &TypeInfo<R(*)(const void*, typename RealTypeImpl<Args>::type...)>::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; if constexpr (!std::is_trivially_copyable_v<T>){
if constexpr (!is_shallow_copyable){
T obj{}; T obj{};
std::construct_at((T*)ptr, obj); std::construct_at((T*)ptr, obj);
} }
@ -111,7 +103,7 @@ namespace refl {
} }
} }
public: public:
static UClass_Auto<T> BuildClass() { constexpr static UClass_Auto<T> BuildClass() {
auto cls = UClass_Auto<T>(type_name<T>().View(), sizeof(T)); auto cls = UClass_Auto<T>(type_name<T>().View(), sizeof(T));
return cls; return cls;
} }
@ -120,41 +112,52 @@ namespace refl {
template<_ReflCheck_Ctor_NoUClass T> template<_ReflCheck_Ctor_NoUClass T>
struct TypeInfoImpl<T>{ struct TypeInfoImpl<T>{
using UClass = UClass_Auto<T>; using UClass = UClass_Auto<T>;
inline static UClass StaticClass = UClass::BuildClass(); inline constexpr static UClass StaticClass = UClass::BuildClass();
}; };
/*
*
* const void*
*
*/
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<const UClass*, sizeof...(Args) + 1> UList{};
std::vector<UClass*> GetParams()const override { std::vector<const UClass*> GetParams()const override {
return { UList.data(), UList.data() + UList.size()}; return { UList.data(), UList.data() + UList.size()};
} }
void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList)const override { void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList)const override {
Call<Args...>(field, ArgsList); if constexpr (std::is_same_v<R, void>) {
} MethodType fptr = (MethodType)std::get<Method>(field.data);
protected: auto param = ArgsList.rbegin();
template<typename... Args> fptr(param++->cast_to<Args>()...);
inline void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList)const { }
MethodType fptr = (MethodType)std::get<Method>(field.data); else {
int Indices = 0; MethodType fptr = (MethodType)std::get<Method>(field.data);
//fptr(ArgsList[1].val, Indices, Indices); auto param = ArgsList.rbegin();
//fptr(std::forward<Args>((Args)Indices), ...); auto ret = ArgsList.begin();
int a = 1; if (ret->cls == &TypeInfo<R>::StaticClass) {
a = a + 1; *(R*)ret->val = fptr(param++->cast_to<Args>()...);
}
else {
fptr(param++->cast_to<Args>()...);
}
}
} }
public: public:
//为了简化判断cls 对象 统统指向 T*
static UMethod_Auto<R,Args...> BuildClass() { static UMethod_Auto<R,Args...> BuildClass() {
auto cls = UMethod_Auto<R, Args...>(type_name<MethodType>().View(), sizeof(MethodType)); UMethod_Auto<R,Args...> cls(type_name<MethodType>().View(), sizeof(MethodType));
if constexpr(!std::is_same<R, void>::value) { if constexpr(!std::is_same_v<R, void>) {
cls.UList[0] = &TypeInfo<R>::StaticClass; cls.UList[0] = &TypeInfo<R>::StaticClass;
} }
if (sizeof...(Args) > 0) { if (sizeof...(Args) > 0) {
auto ptr = &cls.UList[1]; auto ptr = &cls.UList[1];
(...,(*ptr = &TypeInfo<Args>::StaticClass, ptr++)); (...,(*ptr = &TypeInfo<typename std::remove_pointer_t<Args>*>::StaticClass, ptr++));
} }
return cls; return cls;
} }
@ -175,11 +178,14 @@ _cache_get: bool isChild = cache->type->IsChildOf<T>(true);
} }
return isChild; return isChild;
} }
auto field = cls->GetField(name); auto field = cls->GetField(name, false);
if (field) { if (field) {
cache = field; cache = field;
goto _cache_get; goto _cache_get;
} }
if (cls->parent) {
return Parent().Get(name, t);
}
return false; return false;
} }
template<typename T> template<typename T>
@ -193,18 +199,24 @@ _cache_set: bool isChild = cache->type->IsChildOf<T>(true);
} }
return isChild; return isChild;
} }
auto field = cls->GetField(name); auto field = cls->GetField(name, false);
if (field) { if (field) {
cache = field; cache = field;
goto _cache_set; goto _cache_set;
} }
if (cls->parent) {
return Parent().Set(name, t);
}
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, true);
if (!field) { if (!field) {
if (cls->parent) {
return Parent().Invoke(name, args...);
}
return false; return false;
} }
constexpr int inputSize = sizeof...(Args); constexpr int inputSize = sizeof...(Args);
@ -218,41 +230,66 @@ _cache_set: bool isChild = cache->type->IsChildOf<T>(true);
ArgsList.reserve(paramsSize); ArgsList.reserve(paramsSize);
ArgsList.emplace_back(); ArgsList.emplace_back();
if (member) { if (member) {
ArgsList.emplace_back(ptr, cls ); ArgsList.emplace_back(ptr, &TypeInfo<const void*>::StaticClass);
} }
(..., (ArgsList.emplace_back((void*)&args, &TypeInfo<Args>::StaticClass))); (..., (ArgsList.emplace_back(args)));
for (int i = member + 1; i < paramsSize; i++) { for (int i = member + 1; i < paramsSize; i++) {
if (ArgsList[i].cls != params[i]) { if (ArgsList[i].cls != params[i]) {
ArgsList[i].ConvertTo(params[i]); if (!ArgsList[i].ConvertTo(params[i])) {
return false;
}
} }
} }
field->type->Call(*field, ArgsList); field->type->Call(*field, ArgsList);
return false;
}
template<typename R, typename ...Args>
inline bool ObjectView::InvokeRet(const Name& name, R& ret, Args&& ...args)
{
auto field = cls->GetField(name);
if (!field) {
return false;
}
if (field->flag & FIELD_MEMBER_FLAG) {
using MemberMethodType = R(*)(const void*, Args...);
MemberMethodType fptr = (MemberMethodType)std::get<Method>(field->data);
ret = fptr(ptr, std::forward<Args>(args)...);
}
else {
using MethodType = R(*)(Args...);
MethodType fptr = (MethodType)std::get<Method>(field->data);
ret = fptr(std::forward<Args>(args)...);
}
return true; return true;
} }
bool ArgsView::ConvertTo(UClass* toClass) { template<_ReflCheck_Ctor R, typename ...Args>
ArgsView args{val}; R ObjectView::Invoke(const Name& name, Args&&... args)
cls->ConvertToValue(args); {
if (args.cls == toClass) { auto field = cls->GetField(name, true);
*this = args; if (!field) {
if (cls->parent) {
return Parent().Invoke<R>(name, args...);
}
return {};
}
R ret{};
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(ret);
if (member) {
ArgsList.emplace_back(ptr, &TypeInfo<const void*>::StaticClass);
}
(..., (ArgsList.emplace_back(args)));
for (int i = 0; i < paramsSize; i++) {
if (ArgsList[i].cls != params[i]) {
if (!ArgsList[i].ConvertTo(params[i])) {
return ret;
}
}
}
field->type->Call(*field, ArgsList);
return ret;
}
ObjectView ObjectView::Parent() {
return { ptr, cls ? cls->parent : nullptr };
}
/*平凡对象的转化要支持吗
*
*
*
*/
bool ArgsView::ConvertTo(const UClass* toClass) {
//子类转父类
if (cls->IsChildOf(toClass)) {
cls = toClass;
return true; return true;
} }
return false; return false;

View File

@ -1,4 +1,6 @@
#pragma once
#include <string> #include <string>
#include "type.h"
namespace refl { namespace refl {
class UClass; class UClass;
class FieldPtr; class FieldPtr;
@ -19,14 +21,31 @@ namespace refl {
template<typename ...Args> template<typename ...Args>
bool Invoke(const Name& name, Args&&... args); bool Invoke(const Name& name, Args&&... args);
template<typename R, typename ...Args> template<_ReflCheck_Ctor R, typename ...Args>
bool InvokeRet(const Name& name,R& ret, Args&&... args); R Invoke(const Name& name, Args&&... args);
ObjectView Parent();
}; };
class ArgsView { class 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) {}
bool ConvertTo(UClass* toClass); template<typename T>
ArgsView(T&& v): val(&v), cls(&TypeInfo<typename std::remove_reference_t<T>*>::StaticClass){}
template<typename T>
inline T cast_to() {
if constexpr (std::is_pointer_v<T>) {
return (T)val;
}
else if constexpr (std::is_reference_v<T>){
using RT = std::remove_reference_t<T>;
return *(RT*)val;
}else{
return *(T*)val;
}
}
bool ConvertTo(const UClass* toClass);
}; };
} }

View File

@ -7,7 +7,10 @@
using namespace std; using namespace std;
using namespace refl; using namespace refl;
struct vec3_parent { struct vec3_parent {
virtual void norm(int x1, int& x2) {
x2 = x1 * x2;
cout << x2 << "vec3_parent::norm" << endl;
}
}; };
struct vec3 : public vec3_parent { struct vec3 : public vec3_parent {
using UClass = class vec3_UClass; using UClass = class vec3_UClass;
@ -15,10 +18,6 @@ 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, int& x2) {
x2 = x1 * x * y * z * x2;
cout << x2 << "::norm" << endl;
}
virtual float norm1(int x1 = 10) { virtual float norm1(int x1 = 10) {
cout << x1 << "::norm1" << endl; cout << x1 << "::norm1" << endl;
return x * y *z * x1; return x * y *z * x1;
@ -34,11 +33,18 @@ struct vec3 : public vec3_parent {
struct vec3_UClass : public UClass { struct vec3_UClass : public UClass {
public: public:
array<FieldPtr,6> FList; array<FieldPtr,6> FList;
int32_t AttrNum;
using UClass::UClass; using UClass::UClass;
const FieldPtr* GetField(const Name& name)const override { const FieldPtr* GetField(const Name& name, bool isMethod)const override {
for (auto& field : FList) { // 指定开始位置的迭代器
if (field.name == name) { auto start = FList.begin();
return &field; if (isMethod) {
start += AttrNum;
}
auto end = FList.end();
for (auto it = start; it != end; ++it) {
if (it->name == name) {
return &*it;
} }
} }
return nullptr; return nullptr;
@ -50,11 +56,12 @@ 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<float, offsetof(vec3, x)>("x"); cls.AttrNum = 3;
cls.FList[1] = cls.MakeMemberField<float, offsetof(vec3, y)>("y"); cls.FList[0] = cls.MakeMemberField<offsetof(vec3, x)>("x", &TypeInfo<float>::StaticClass);
cls.FList[2] = cls.MakeMemberField<float, offsetof(vec3, z)>("z"); cls.FList[1] = cls.MakeMemberField<offsetof(vec3, y)>("y", &TypeInfo<float>::StaticClass);
cls.FList[2] = cls.MakeMemberField<offsetof(vec3, z)>("z", &TypeInfo<float>::StaticClass);
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;
} }
@ -63,31 +70,48 @@ template<typename ...Args>
void printt(void* ptr, std::vector<ArgsView>& ArgsList) { void printt(void* ptr, std::vector<ArgsView>& ArgsList) {
using MethodType = void (*)(Args...); using MethodType = void (*)(Args...);
MethodType fptr = (MethodType)ptr; MethodType fptr = (MethodType)ptr;
auto param = ArgsList.begin(); {
auto val1 = (++param)->val; auto param = ArgsList.rbegin();
auto val2 = (++param)->val; fptr(param++->cast_to<Args>()...);
auto val3 = (++param)->val; //fptr((Args)param++->val...);
fptr(val1, (int)val2, (int*)(void *)val3); }
//fptr(val1, (int)val2, std::forward<int&>((int&)val3)); /* {
auto param = ArgsList.begin();
auto val1 = (++param);
auto val2 = (++param);
auto val3 = (++param);
fptr(val1->cast_to<void *>(), val1->cast_to<void*>(), val1->cast_to<void*>();
}
*/
//fptr((++param)->val, (int)(++param)->val, (int&)(++param)->val); //fptr((++param)->val, (int)(++param)->val, (int&)(++param)->val);
//fptr(std::forward<Args>(Args(param++->val))...); //fptr(std::forward<Args>((Args)(++param)->val)...);
int x = 1; int x = 1;
x = x + 1; x = x + 1;
} }
int main() { int main() {
auto cls = &TypeInfo<vec3>::StaticClass; auto cls = &TypeInfo<vec3>::StaticClass;
auto cls2 = &TypeInfo<int>::StaticClass;
auto cls3 = &TypeInfo<int*>::StaticClass;
auto cls4 = &TypeInfo<void*>::StaticClass;
auto cls5 = &TypeInfo<decltype(&vec3::norm)>::StaticClass;
vec3 v; vec3 v;
int x = 1, y = 2; int x = 1, y = 2;
std::vector<ArgsView> ArgsList; std::vector<ArgsView> ArgsList;
ArgsList.emplace_back(); ArgsList.emplace_back();
ArgsList.emplace_back(&v); ArgsList.emplace_back(v);
ArgsList.emplace_back((void*)x); ArgsList.emplace_back(x);
ArgsList.emplace_back(&y); ArgsList.emplace_back(y);
auto ptr1 = &vec3::norm; auto ptr1 = &vec3::norm;
using MethodType = void (*)(void*, int, int*); using MethodType = void (*)(void*, int, int&);
MethodType ptr2 = *(MethodType*)&ptr1; MethodType ptr2 = *(MethodType*)&ptr1;
ptr2(&v, x , &y); using R = int;
printt<const void*, int , int*>(*(void**)&ptr1, ArgsList); using RetType = void*;
auto ttt = sizeof(void*);
RetType ret;
//ptr2(&v, x , y);
auto ov = cls->New((void*)& v);
ov.Invoke("norm", x, y);
printt<const void*, int , int&>(*(void**)&ptr1, ArgsList);
//ptr2(x, y); //ptr2(x, y);
//cout << "hello world\n"; cout << "hello world\n";
} }