update refl

This commit is contained in:
ouczbs 2024-06-14 22:24:52 +08:00
parent a5bfccc1d8
commit 659cdc0f46
15 changed files with 192 additions and 147 deletions

View File

@ -3,6 +3,6 @@ includes("**/xmake.lua")
add_requires("spdlog")
add_requires("tinyobjloader")
add_requires("vulkansdk")
add_requires("assimp")
add_requires("assimp v5.4.0")
add_requires("nlohmann_json")
add_requires("benchmark")

View File

@ -2,6 +2,7 @@
#include "type.h"
namespace refl {
class UClass;
class FieldPtr;
//生命周期短,适用于传参,不建议保存数据
//只能指向指针,引用=>指针,指针=>指针T => T*,T的类型丢失
struct Any {
@ -15,14 +16,14 @@ namespace refl {
//右值=>右值压入栈caller入栈地址
//左值=>caller变量地址
template<typename T>
constexpr Any(T&& v) : ptr(&v), cls(&TypeInfo<args_type_t<T>*>::StaticClass) {
constexpr Any(T&& v) : ptr(&v), cls(&TypeInfo<args_type_t<T>>::StaticClass) {
if constexpr (std::is_same_v<args_type_t<T>, Any>) {
ptr = v.ptr;
cls = v.cls;
}
}
template<typename T>
constexpr Any(T* v) : ptr(v), cls(&TypeInfo<args_type_t<T>*>::StaticClass) {
constexpr Any(T* v) : ptr(v), cls(&TypeInfo<args_type_t<T>>::StaticClass) {
if constexpr (std::is_same_v<args_type_t<T>, Any>) {
ptr = v->ptr;
cls = v->cls;
@ -50,5 +51,11 @@ namespace refl {
constexpr Any Change(const void* ptr)const {
return {ptr, cls};
}
Any Member(const FieldPtr& field)const;
Any Member(int i)const;
int ArraySize()const;
bool IsArray()const;
bool IsObject()const;
bool Construct(const zstd::sarray<Any>& ArgsList)const;
};
}

View File

@ -9,6 +9,8 @@ namespace refl {
protected:
static ConvertMap BuildClassMap();
public:
static bool ToInt32(Any& dst, const Any& src);
static bool ToFloat(Any& dst, const Any& src);
static bool ToString(Any& dst,const Any& src);
static bool Construct(Any& dst, const Any& src);
inline static ConvertMap ClassMap = BuildClassMap();

View File

@ -4,12 +4,28 @@
namespace refl {
inline bool Convert::ToString(Any& dst, const Any& src)
{
if (src.Parent() == &TypeInfo<char>::StaticClass) {
if (src.cls == &TypeInfo<char>::StaticClass) {
std::construct_at(dst.CastTo<std::string*>(), src.CastTo<const char*>());
return true;
}
return false;
}
inline bool Convert::ToInt32(Any& dst, const Any& src)
{
if (src.cls == &TypeInfo<float>::StaticClass) {
*dst.CastTo<int*>() = *src.CastTo<float*>();
return true;
}
return false;
}
inline bool Convert::ToFloat(Any& dst, const Any& src)
{
if (src.cls == &TypeInfo<int>::StaticClass) {
*dst.CastTo<float*>() = *src.CastTo<int*>();
return true;
}
return false;
}
inline bool Convert::Construct(Any& dst, const Any& src)
{
if (dst.cls->CtorObject((void*)dst.ptr, src)) {
@ -24,7 +40,10 @@ namespace refl {
inline ConvertMap Convert::BuildClassMap()
{
ConvertMap classMap;
classMap.emplace(&TypeInfo<std::string*>::StaticClass, &ToString);
classMap.emplace(&TypeInfo<std::string>::StaticClass, &ToString);
classMap.emplace(&TypeInfo<int>::StaticClass, &ToInt32);
classMap.emplace(&TypeInfo<uint32_t>::StaticClass, &ToInt32);
classMap.emplace(&TypeInfo<float>::StaticClass, &ToFloat);
return classMap;
}
}

View File

@ -63,8 +63,9 @@ namespace refl {
//safe
bool Invoke(svector<Any>& ArgsList)const;
template<typename TArgsList>
bool Invokes(TArgsList& ArgsList)const;
//const sarray || svector
template<typename SArgsList>
bool Invokes(SArgsList& ArgsList)const;
template<typename Func, typename... Args>
auto Call(Func func, Args&&... args)const;

View File

@ -45,8 +45,8 @@ namespace refl {
}
return Call;
}
template<typename TArgsList>
inline bool FieldPtr::Invokes(TArgsList& ArgsList)const {
template<typename SArgsList>
inline bool FieldPtr::Invokes(SArgsList& ArgsList)const {
auto Call = type->vtable.Call;
if (Call) {
sarray<const UClass*> params = GetParams();

View File

@ -32,7 +32,7 @@ namespace refl {
class Meta {
public:
template<typename T, typename... Args>
static FieldPtr CtorField(char*& memory, const MemberData& data = {});
static FieldPtr CtorField(char*& memory, const MethodData& data = {});
template<typename T, typename Obj>
static FieldPtr MemberField(T Obj::* ptr, const Name& name, char*& memory, const MemberData& data = {});

View File

@ -4,12 +4,16 @@
#include "convert.h"
namespace refl {
template<typename T, typename ...Args>
inline FieldPtr Meta::CtorField(char*& memory, const MemberData& data)
void NewCtor(void* mem, Args... args) {
new (mem) T(std::forward<Args>(args)...);
}
template<typename T, typename ...Args>
inline FieldPtr Meta::CtorField(char*& memory, const MethodData& data)
{
MethodData method;
uint32_t flag = FIELD_MEMBER_FLAG | FIELD_CTOR_FLAG;
constexpr auto cls = &TypeInfo<void(*)(const void*, real_type_t<Args>...)>::StaticClass;
if (data.value.IsValid()) {
if (data.value.valid()) {
flag |= FIELD_CTOR_VALUE_FLAG;
AnyArgs args(data.value, cls->GetParams(), memory);
method.value = args.ToSArray();
@ -20,17 +24,14 @@ namespace refl {
Convert::Construct(method.meta, data.meta);
memory += data.meta.Size();
}
static auto ptr = [](void* mem, Args... args) {
new (mem) T(std::forward<Args>(args)...);
};
method.fptr = { *(Method*)&ptr };
method.fptr = { (Method)&NewCtor<T, Args...> };
return { FName("Ctor"), cls, method,flag};
}
template<typename T, typename Obj>
inline FieldPtr Meta::MemberField(T Obj::* ptr, const Name& name, char*& memory, const MemberData& data)
{
MemberData member;
auto cls = &TypeInfo<T*>::StaticClass;
auto cls = &TypeInfo<T>::StaticClass;
member.offset = reinterpret_cast<std::size_t>(&(reinterpret_cast<const Obj*>(0)->*ptr));
if (data.value.IsValid()) {
member.value = Any(memory, cls);

View File

@ -54,17 +54,18 @@ namespace refl {
}
template<typename T>
T* New(T* ptr = nullptr, const sarray<Any>& ArgsList = {}) const{
if (!IsChildOf<T>()) {
if (!IsChildOf<T>(true)) {
return nullptr;
}
if (ptr == nullptr) {
ptr = (T*)malloc(size);
}
CtorObject(ptr, ArgsList);
return ptr;
}
bool IsChildOf(const UClass* cls) const {
const UClass* _parent = parent;
bool IsChildOf(const UClass* cls, bool bthis = false) const {
const UClass* _parent = bthis ? this : parent;
while (_parent != nullptr) {
if (_parent == cls) {
return true;
@ -75,7 +76,7 @@ namespace refl {
}
template<typename T>
bool IsChildOf(bool bthis = false) const {
return IsChildOf(&TypeInfo<T>::StaticClass);
return IsChildOf(&TypeInfo<T>::StaticClass, bthis);
}
public:
const sarray<const FieldPtr> GetFields(EFieldFind find, const Name& name)const {
@ -84,28 +85,7 @@ namespace refl {
}
return {};
}
bool CtorObject(void* ptr, const sarray<Any>& ArgsList = {})const {
if (vtable.CtorObject) {
if (vtable.CtorObject(ptr, this, ArgsList)) {
return true;
}
auto& fieldList = GetFields(EFieldFind::FIND_CTOR, FName("Ctor"));
if (fieldList.empty()) {
return false;
}
if (fieldList.size() == 1) {
return fieldList[0]->Invoke(ArgsList);
}
for (auto& field : fieldList) {
if (field.Invokes(ArgsList)) {
return true;
}
}
return false;
}
memset(ptr, 0, size);
return true;
}
bool CtorObject(void* ptr, const sarray<Any>& ArgsList = {})const;
void DestObject(void* ptr)const {
if (vtable.DestObject) {
vtable.DestObject(ptr);
@ -114,17 +94,15 @@ namespace refl {
public:
template<typename T>
static bool CtorObject(void* ptr, const UClass* cls, const sarray<Any>& ArgsList = {}) {
int size = ArgsList.size();
if (size == 0) {
int argsSize = ArgsList.size();
if (argsSize == 0) {
if constexpr (std::is_trivially_constructible_v<T>) {
std::construct_at((T*)ptr);
return true;
}
else {
throw "refl::error:: no default construct function!!!";
}
return false;
}
if (size == 1 && ArgsList[0]->Check(cls)) {
if (argsSize == 1 && ArgsList[0]->Check(cls)) {
*(T*)ptr = *(const T*)ArgsList[0]->ptr;
return true;
}

View File

@ -10,7 +10,6 @@ namespace refl {
public:
consteval static MyUClass BuildClass() {
MyUClass cls(type_name<T>().View(), sizeof(T));
cls.vtable.CtorObject = &MyUClass::CtorObject<T>;
if constexpr (std::is_pointer_v<T>){
using RawT = std::remove_pointer_t<T>;
cls.flag = CLASS_POINTER_FLAG;
@ -18,6 +17,9 @@ namespace refl {
cls.parent = &TypeInfo<RawT>::StaticClass;
}
}
else {
cls.vtable.CtorObject = &MyUClass::CtorObject<T>;
}
if constexpr (requires {typename T::MyMetas; }) {
cls.vtable.GetMeta = &T::MyMetas::GetMeta;
}
@ -81,7 +83,7 @@ namespace refl {
MethodType fptr = (MethodType)field->data.method.fptr;
auto param = ArgsList.end();
auto ret = ArgsList.front();
if (ret->cls == &TypeInfo<R*>::StaticClass) {
if (ret->cls == &TypeInfo<R>::StaticClass) {
*(R*)ret->ptr = fptr((param--->CastTo<Args>())...);
}
else {
@ -92,11 +94,11 @@ namespace refl {
protected:
consteval void BuildUList() {
if constexpr (!std::is_same_v<R, void>) {
UList[0] = &TypeInfo<R*>::StaticClass;
UList[0] = &TypeInfo<R>::StaticClass;
}
if constexpr (sizeof...(Args) > 0) {
auto ptr = &UList[1];
(..., (*ptr = &TypeInfo<args_type_t<Args>*>::StaticClass, ptr++));
(..., (*ptr = &TypeInfo<args_type_t<Args>>::StaticClass, ptr++));
}
}
public:
@ -127,6 +129,7 @@ namespace refl {
vtable.GetMeta = &T::MyMetas::GetMeta;
}
vtable.GetFields = &UClass_Meta::GetFields;
vtable.CtorObject = &UClass::CtorObject<T>;
}
const FieldPtr* GetField(int index) const {
return &Fields[index];
@ -191,27 +194,30 @@ namespace refl {
}
};
//基础类型的偏特化
template<_ReflCheck_Ctor_NoUClass T>
struct TypeInfoImpl<T> {
using UClass = UClass_Auto<T>;
inline constexpr static UClass StaticClass = UClass::BuildClass();
};
// 函数指针类型的偏特化
template<typename R, typename... Args>
struct TypeInfoImpl<R(*)(Args...)> {
using UClass = UMethod_Auto<R, Args...>;
inline constexpr static UClass StaticClass = UClass::BuildClass();
template<>
struct TypeInfoImpl<void> {
inline constexpr static UClass StaticClass = { type_name<void>().View(), 0 };
};
template<_ReflCheck_UClass T>
struct TypeInfoImpl<T> {
using MyUClass = typename T::MyMeta::MyUClass;
inline static MyUClass StaticClass = MyUClass();
};
// 函数指针类型的偏特化
template<typename R, typename... Args>
struct TypeInfoImpl<R(*)(Args...)> {
using UClass = UMethod_Auto<R, Args...>;
inline constexpr static UClass StaticClass = UClass::BuildClass();
};
template<typename T, int N>
struct TypeInfoImpl<T[N]> {
using UClass = UClass_Array<T,N>;
inline constexpr static UClass StaticClass = UClass::BuildClass();
};
//基础类型的偏特化
template<_ReflCheck_Ctor_NoUClass T>
struct TypeInfoImpl<T> {
using UClass = UClass_Auto<T>;
inline constexpr static UClass StaticClass = UClass::BuildClass();
};
}

View File

@ -8,20 +8,54 @@ namespace refl {
if (cls == toClass) {
return true;
}
auto p1 = cls->parent;
auto p2 = toClass->parent;
assert(p1 && p2);
//子类转父类
return p1->IsChildOf(p2);
if (!cls) {
return false;
}
return cls->IsChildOf(toClass);
}
inline constexpr int Any::Size()const
{
return cls->parent->size;
return cls->size;
}
inline constexpr const UClass* Any::Parent()const
{
return cls->parent;
}
inline Any Any::Member(const FieldPtr& field)const
{
if (field.flag & FIELD_MEMBER_FLAG) {
return { (const char*)ptr + field.data.member.offset, field.type };
}
return {};
}
inline Any Any::Member(int i) const
{
if (cls->flag & CLASS_ARRAY_FLAG) {
int offset = i * cls->parent->size;
if(offset < cls->size)
return { (const char*)ptr + offset, cls->parent };
}
return Any();
}
inline int Any::ArraySize()const
{
if (cls->flag & CLASS_ARRAY_FLAG) {
return cls->size / cls->parent->size;
}
return 0;
}
inline bool Any::IsArray() const
{
return cls->flag & CLASS_ARRAY_FLAG;
}
inline bool Any::IsObject() const
{
return !(cls->flag & CLASS_ARRAY_FLAG) && !(cls->flag & CLASS_POINTER_FLAG);
}
inline bool Any::Construct(const sarray<Any>& ArgsList) const
{
return cls->CtorObject((void*)ptr, ArgsList);
}
inline AnyArgs::AnyArgs(const sarray<Any>& args, const sarray<const UClass*>& params, void* memory)
: data(memory), num(args.size()), size(GetArgsSize(args, params))
{
@ -39,7 +73,7 @@ namespace refl {
any->ptr = pData;
assert(Convert::Construct(*any, arg));
any++;
pData += (*uptr)->parent->size;
pData += (*uptr)->size;
}
}
inline AnyArgs::~AnyArgs()
@ -74,7 +108,7 @@ namespace refl {
Offset offset = args.size() * sizeof(Any);
auto uptr = params.at(params.size() - args.size());
for (auto uend = params.back(); uptr < uend; uptr++) {
offset += (*uptr)->parent->size;//数据大小
offset += (*uptr)->size;//数据大小
}
return offset;
}
@ -179,4 +213,37 @@ namespace refl {
inline AnyView AnyView::Parent() {
return { ptr, cls ? cls->parent : nullptr };
}
inline bool UClass::CtorObject(void* ptr, const sarray<Any>& ArgsList) const
{
if (vtable.CtorObject) {
if (vtable.CtorObject(ptr, this, ArgsList)) {
return true;
}
auto& fieldList = GetFields(EFieldFind::FIND_CTOR, FName("Ctor"));
if (fieldList.empty()) {
return false;
}
std::array<Any, 10> ArgsArray = { Any{} , Any{ptr} };
int i = 2;
for (auto& arg : ArgsList) {
ArgsArray[i++] = arg;
}
sarray<Any> FieldArgs(&ArgsArray[0], 2 + ArgsList.size());
if (fieldList.size() == 1) {
return fieldList[0]->Invoke(FieldArgs);
}
for (auto& field : fieldList) {
if (field.Invokes(FieldArgs)) {
return true;
}
}
return false;
}
if (ArgsList.valid() && ArgsList[0]->Check(this)) {
memcpy(ptr, ArgsList[0]->ptr, size);
return true;
}
memset(ptr, 0, size);
return true;
}
}

View File

@ -7,7 +7,7 @@
#include "macro.h"
namespace refl {
template<typename T, typename... Args>
consteval FieldPtr StaticCtorField(const MemberData& data = {}) {
consteval FieldPtr StaticCtorField(const MethodData& data = {}) {
uint32_t flag = FIELD_CTOR_FLAG;
auto cls = &TypeInfo<void(*)(void*, real_type_t<Args>...)>::StaticClass;
Offset offset = AnyArgs::GetArgsSize(data.value, cls->GetParams());

View File

@ -14,36 +14,19 @@ struct vec3 : public vec3_parent {
UPROPERTY_vk({ 1.f})
float x = 1;
UPROPERTY_dx({ 2.f})
float y = 2;
int y = 2;
UPROPERTY({ 5.f})
float z = 3;
uint32_t z = 3;
UPROPERTY({ "hello meta"})
string name = "???";
UFUNCTION({ {3,4} })
int norm(int x1, int& x2)override {
int tmp = x1 * 2 + 1;
x1 = x2;
x2 = tmp;
return x2;
//cout << x2 << "vec3::norm" << endl;
}
string name = "???a";
UFUNCTION({})
virtual float norm1(int& x1) {
x1 = x1 * x * y * z;
vec3() {
}
UFUNCTION({1, 2.f, 3.f})
vec3(float x1, int y1, uint32_t z1) {
x = x1;
y = x1 - 1;
//z = x1 - 10;
//cout << x1 << "::norm1" << endl;
return x1;
}
UFUNCTION({})
static void norm2(int x1 = 10) {
cout << x1 << "::norm2" << endl;
}
UFUNCTION({})
static void norm3(int x1 = 10) {
x1 = x1 * 10;
cout << x1 << "::norm3" << endl;
y = y1;
z = z1;
}
};
#include "vertex_gen.inl"

View File

@ -1,49 +1,16 @@
#include "refl/vertex.h"
#include <benchmark/benchmark.h>
auto cls = &TypeInfo<vec3>::StaticClass;
vec3 v;
auto ov = cls->New((void*)&v);
void TestRefl1(benchmark::State& state) {
int x = 1, y = 2;
auto f = cls->GetField(GetStaticFieldID<vec3_Meta>(FName("name")));
string hello;
ov.Get(FName("name"), hello);
hello = *f->data.member.value.CastTo<string*>();
ov.Set(FName("name"), hello);
constexpr auto r = StaticMemberField(&vec3::name, FName("name"), { ("hello meta")});
for (auto _ : state) {
std::array<Any, 4> arr{&x, ov.ptr};
svector<Any> svec(arr, 2);
ov.Invoke(FName("norm"), svec);
}
}
BENCHMARK(TestRefl1);
void TestRefl2(benchmark::State& state) {
int x = 1, y = 2;
constexpr auto id = GetStaticFieldID<vec3_Meta>(FName("norm"));
auto field = cls->GetField(id);
for (auto _ : state) {
std::array<Any, 4> arr{&x, ov.ptr};
svector<Any> svec(arr, 2);
field->Invoke(svec);
}
}
BENCHMARK(TestRefl2);
void TestRefl3(benchmark::State& state) {
int x = 1, y = 2;
constexpr auto id = GetStaticFieldID<vec3_Meta>(FName("norm"));
auto field = cls->GetField(id);
for (auto _ : state) {
field->Invoke({ &x,ov.ptr, x, y });
}
}
BENCHMARK(TestRefl3);
void TestCPlusPlus(benchmark::State& state) {
int x = 1, y = 2;
for (auto _ : state) {
x = v.norm(x, y);
}
}
BENCHMARK(TestCPlusPlus);
BENCHMARK_MAIN();
int main() {
vec3 v;
float x = sizeof(*cls);
v.x = 333;
v.y = 334;
v.z = 335;
v.name = "336";
void* ptr;
auto rx = Any(ptr);
auto ov = cls->New(&v);
//ov.Get("FName", x);
return -1;
}

View File

@ -3,8 +3,10 @@ add_requires("UTemplate")
target("zlib")
set_kind("static")
add_packages("UTemplate", {public = true})
add_defines("YAML_CPP_STATIC_DEFINE", {public = true})
add_includedirs("include", {public = true})
add_headerfiles("include/**/*.h", "include/**/*.inl")
add_files("src/**.cpp")
target("zlib_test")
set_kind("binary")
add_deps("zlib")
@ -38,4 +40,16 @@ target("refl_zlib")
add_packages("benchmark")
add_includedirs("test/refl")
add_files("test/refl_01.cpp","test/refl/*.cpp")
add_headerfiles("test/refl/*.h")
add_headerfiles("test/refl/*.h")
target("yaml_zlib")
add_rules("c++.codegen",{
files = {"test/yaml/*.h", "test/yaml/*.hpp"}
})
set_kind("binary")
add_deps("zlib")
add_syslinks("Ole32")
add_packages("benchmark")
add_includedirs("test/yaml")
add_files("test/yaml/*.cpp")
add_headerfiles("test/yaml/*.h")