From 966f7119e7545325458451537830731b89d0a48b Mon Sep 17 00:00:00 2001 From: aozhiwei Date: Tue, 20 Dec 2022 21:23:41 +0800 Subject: [PATCH] add relect --- a8/reflect.h | 276 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 a8/reflect.h diff --git a/a8/reflect.h b/a8/reflect.h new file mode 100644 index 0000000..ceea6c2 --- /dev/null +++ b/a8/reflect.h @@ -0,0 +1,276 @@ +#pragma once + +#include + +namespace a8 +{ + namespace reflect + { + + enum FieldType + { + ET_INT32 = 1, + ET_UINT32 = 2, + ET_INT64 = 3, + ET_UINT64 = 4, + ET_DOUBLE = 5, + ET_STRING = 6, + ET_CLASS = 7, + ET_INTERFACE = 8, + }; + + enum FieldSubType + { + EST_SIMPLE = 1, + EST_SIMPLE_POINTER = 2, + EST_CONTAINRER = 3, + EST_CONTAINRER_POINTER = 4, + }; + + struct Field; + class Class; + typedef bool (*FIELD_FOR_EACH_FUNC)(a8::reflect::Field*, void*, void*); + + struct Field + { + const char* field_name = nullptr; + int type = 0; //int uint int64 uint64 double string class interface class_pointer + int subtype = 0; //std::vector std::list + int offset = 0; + a8::reflect::Class **pp_generic_class = nullptr; //泛型容器类型指针的指针 + void* (*create)() = nullptr; + void (*destroy)(void*) = nullptr; + int (*size)(void*) = nullptr; + void (*for_each)(a8::reflect::Field*, void*, void* , FIELD_FOR_EACH_FUNC) = nullptr; + char* (*push_back)(void*) = nullptr; + }; + + class Class + { + public: + void* (*create)() = nullptr; + void (*destroy)(void*) = nullptr; + void (*copy)(void*, void*) = nullptr; + + Class(const char* classname, int fieldnum, int tag) + { + class_name_ = classname; + tag_ = tag; + fields_ = new a8::reflect::Field[fieldnum]; + fieldnum_ = fieldnum; + } + + a8::reflect::Field* GetDeclaredFields() + { + return fields_; + } + + int FieldNum() + { + return fieldnum_; + } + + int ClassId() + { + return class_id_; + } + + int Tag() + { + return tag_; + } + + void SetField(int fieldidx, + const char* fieldname, + int type, + int subtype, + int offset, + a8::reflect::Class **pp_generic_class, + void* (*create)(), + void (*destroy)(void*), + int (*size)(void*), + void (*for_each)(a8::reflect::Field*, void*, void*, FIELD_FOR_EACH_FUNC), + char* (*push_back)(void*) + ) + { + a8::reflect::Field *p = fields_ + fieldidx; + p->field_name = fieldname; + p->type = type; + p->subtype = subtype; + p->offset = offset; + p->pp_generic_class = pp_generic_class; + p->create = create; + p->destroy = destroy; + p->size = size; + p->for_each = for_each; + p->push_back = push_back; + } + + int GetFieldIdx(int offset) + { + for (int i = 0; i < fieldnum_; i++) { + if (fields_[i].offset == offset) { + return i; + } + } + return -1; + } + + const char* ClassName() + { + return class_name_; + } + private: + int class_id_ = 0; + int tag_ = 0; + int fieldnum_ = 0; + const char* class_name_ = nullptr; + a8::reflect::Field* fields_ = nullptr; + }; + + template + static void* _create() + { + return (void*) new T(); + } + + template + static void _destroy(void* instance) + { + T* p = (T*)instance; + delete p; + } + + template + static void _copy(void* a, void* b) + { + *(T*)a = *(T*)b; + } + + template + static int _size(void* instance) + { + T* p = (T*)instance; + return p->size(); + } + + template + static void _for_each(a8::reflect::Field* field, void* instance, void* userdata, + FIELD_FOR_EACH_FUNC callback) + { + T* p = (T*)instance; + for (auto &itr : *p) { + if (callback && !callback(field, userdata, (void*)&itr)) { + break; + } + } + } + + template + static char* _push_back(void* instance) + { + T* p = (T*)instance; + return (char*)&a8::FastAppend(*p); + } + + template + inline a8::reflect::Class** get_pp_generic_class(a8::ReflectibleObject& obj) + { + return &T::__metaclass; + } + + template + inline a8::reflect::Class** get_pp_generic_class(const T& obj) + { + return nullptr; + } + + } +} + +#define my_offsetof2(TYPE, MEMBER) \ + ((size_t)((char *)&(((TYPE *)0x10)->MEMBER) - (char*)0x10)) + +#define container_of2(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - my_offsetof2(type,member) );}) + +#define BEGIN_MSG_CLASS(classname, fieldnum) \ + { \ + a8::reflect::Class *metaclass = new a8::reflect::Class(#classname, fieldnum, classname::CLSID); \ + metaclass->create =&a8::reflect::_create; \ + metaclass->destroy =&a8::reflect::_destroy; \ + metaclass->copy =&a8::reflect::_copy; \ + classname::__metaclass = metaclass; \ + classname p; + +#define END_MSG_CLASS() \ + } + +#define BEGIN_MFMSG_CLASS(classname, fieldnum) \ + { \ + a8::reflect::Class *metaclass = new a8::reflect::Class(#classname, fieldnum, classname::CLSID); \ + metaclass->create =&a8::reflect::_create; \ + metaclass->destroy =&a8::reflect::_destroy; \ + metaclass->copy =&a8::reflect::_copy; \ + classname::__metaclass = metaclass; \ + assert(classname::CLSID < 1024); \ + s_mfclass_metaclasses[classname::CLSID] = metaclass; \ + classname p; + +#define END_MFMSG_CLASS() \ + } + +#define DEFINE_SIMPLE_FIELD(fieldidx, fieldname, type) \ + metaclass->SetField(fieldidx, \ + #fieldname, \ + type, \ + a8::reflect::EST_SIMPLE, \ + my_offsetof2(decltype(p), fieldname), \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL); + +#define DEFINE_SIMPLE_POINTER_FIELD(fieldidx, fieldname, type) \ + metaclass->SetField(fieldidx, \ + #fieldname, \ + type, \ + a8::reflect::EST_SIMPLE_POINTER, \ + my_offsetof2(decltype(p), fieldname), \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL, \ + NULL); + +#define DEFINE_CONTAINRER_FIELD(fieldidx, fieldname, type) \ + metaclass->SetField(fieldidx, \ + #fieldname, \ + type, \ + a8::reflect::EST_CONTAINRER, \ + my_offsetof2(decltype(p), fieldname), \ + a8::reflect::get_pp_generic_class(p.fieldname), \ + &a8::reflect::_create, \ + &a8::reflect::_destroy, \ + &a8::reflect::_size, \ + &a8::reflect::_for_each , \ + &a8::reflect::_push_back \ + ); + +#define DEFINE_CONTAINRER_POINTER_FIELD(fieldidx, fieldname, type) \ + metaclass->SetField(fieldidx, \ + #fieldname, \ + type, \ + a8::reflect::EST_CONTAINRER_POINTER, \ + my_offsetof2(decltype(p), fieldname), \ + a8::reflect::get_pp_generic_class(p.fieldname), \ + &a8::reflect::_create, \ + &a8::reflect::_destroy, \ + &a8::reflect::_size, \ + &a8::reflect::_for_each , \ + &a8::reflect::_push_back \ + );