From 6d4d39ee4e702ba87a5bd3e9cf62a5a51880ea69 Mon Sep 17 00:00:00 2001 From: ouczbs Date: Fri, 21 Jun 2024 22:20:13 +0800 Subject: [PATCH] refl support overload --- src/refl/ClassMeta.cs | 63 ++++++++++++++++++++--------- src/refl/GenMeta.cs | 15 ++++--- src/refl/MetaToken.cs | 31 ++++++++------- src/refl/OverTree.cs | 74 +++++++++++++++++++++++++++++++++++ src/refl/_install.bat | 6 +++ src/refl/cpp/macro.h | 17 ++++---- src/refl/cpp/vertex.h | 74 +++++++++++------------------------ src/refl/template/meta.liquid | 12 ++++-- 8 files changed, 189 insertions(+), 103 deletions(-) create mode 100644 src/refl/OverTree.cs create mode 100644 src/refl/_install.bat diff --git a/src/refl/ClassMeta.cs b/src/refl/ClassMeta.cs index 30252e2..62939c2 100644 --- a/src/refl/ClassMeta.cs +++ b/src/refl/ClassMeta.cs @@ -1,5 +1,7 @@ using CppAst; using Irony; +using static System.Net.Mime.MediaTypeNames; +using static System.Runtime.InteropServices.JavaScript.JSType; namespace refl { @@ -7,11 +9,13 @@ namespace refl { public string Name { get; set; } public string Meta { get; set; } - + public string Ref { get; set; } + //public Dictionary UserMeta = new Dictionary(); public FieldData(string name, string meta) { Name = name; - Meta = meta; + Meta = "{" + meta + "}"; + Ref = ""; } } @@ -46,8 +50,10 @@ namespace refl { public static HashSet NameSet = new HashSet(); public string NameSpace { get; set; } - public List ClassList; + public List ClassList; public List ChildList; + + public static OverTree OverData = new OverTree(); public ModuleMeta(string name_space) { NameSpace = name_space; @@ -71,6 +77,7 @@ namespace refl } } ClassMeta cls_meta = new ClassMeta(cppClass.Name, parentName); + OverData.Clear(); foreach (var field in cppClass.Fields) { if (field.Attributes.Count == 0) @@ -93,17 +100,15 @@ namespace refl foreach (var attribute in func.Attributes) { string key, value; - MetaToken.ParseMeta(attribute.Arguments, out key, out value); + string? next; + MetaToken.ParseAllMeta(attribute.Arguments, out key, out value, out next); + FieldData data = new FieldData(key, value); if (!cls_meta.Fields.ContainsKey(key)) { cls_meta.Fields.Add(key, new FieldMeta()); } - List nameList = new List{ "T" }; - foreach (var parm in func.Parameters) - { - nameList.Add(parm.Type.FullName); - } - cls_meta.Fields[key].CtorList.Add(new FieldData(string.Join(",", nameList), value)); + cls_meta.Fields[key].CtorList.Add(data); + ParseClassUserMeta(cppClass, data, next); } } foreach (var func in cppClass.Functions) @@ -113,23 +118,43 @@ namespace refl foreach (var attribute in func.Attributes) { string key, value; - MetaToken.ParseMeta(attribute.Arguments, out key, out value); + string? next; + MetaToken.ParseAllMeta(attribute.Arguments, out key, out value, out next); + FieldData data = new FieldData(func.Name, value); if (!cls_meta.Fields.ContainsKey(key)) { cls_meta.Fields.Add(key, new FieldMeta()); } - cls_meta.Fields[key].MethodList.Add(new FieldData(func.Name, value)); + cls_meta.Fields[key].MethodList.Add(data); + ParseClassUserMeta(cppClass, data, next); } } return cls_meta; } + public static void ParseClassUserMeta(CppClass cppClass, FieldData data, string? next) + { + if (next == null) + return; + OverData.Init(cppClass); + string key, value; + while (next != null) + { + MetaToken.ParseAllMeta(next, out key, out value, out next); + if (key == "ref") + { + value = OverData.Find(value.Trim()); + data.Ref = value; + } + //data.UserMeta.Add(key, value); + } + } public static ModuleMeta ParseCppNamespaces(CppNamespace cpp) { var module = new ModuleMeta(cpp.Name); foreach (var cppClass in cpp.Classes) { var cls_meta = ParseCppClass(cppClass); - if(cls_meta.Fields.Count > 0) + if (cls_meta.Fields.Count > 0) { module.ClassList.Add(cls_meta); } @@ -137,7 +162,7 @@ namespace refl foreach (var spaces in cpp.Namespaces) { var child = ParseCppNamespaces(spaces); - if(child.ClassList.Count > 0 || child.ChildList.Count > 0) + if (child.ClassList.Count > 0 || child.ChildList.Count > 0) { module.ChildList.Add(child); } @@ -150,12 +175,12 @@ namespace refl foreach (var cppClass in cpp.Classes) { var cls_meta = ParseCppClass(cppClass); - if(cls_meta.Fields.Count > 0) + if (cls_meta.Fields.Count > 0) { module.ClassList.Add(cls_meta); } } - foreach(var spaces in cpp.Namespaces) + foreach (var spaces in cpp.Namespaces) { var child = ParseCppNamespaces(spaces); module.ChildList.Add(child); @@ -166,16 +191,16 @@ namespace refl public static void ParseMetaName(ModuleMeta module) { ParseClassMetaName(module); - foreach(var child in module.ChildList) + foreach (var child in module.ChildList) { ParseMetaName(child); } } public static void ParseClassMetaName(ModuleMeta module) { - foreach(var cls in module.ClassList) + foreach (var cls in module.ClassList) { - foreach(var field in cls.Fields) + foreach (var field in cls.Fields) { if (!NameSet.Contains(field.Key)) { diff --git a/src/refl/GenMeta.cs b/src/refl/GenMeta.cs index 41cc6b7..fc4903e 100644 --- a/src/refl/GenMeta.cs +++ b/src/refl/GenMeta.cs @@ -9,12 +9,14 @@ namespace refl { public string Name { get; set; } public string Meta { get; set; } + public string Ref { get; set; } public int Type { get; set; } - public FieldMetaData(string name, string meta, int type) + public FieldMetaData(FieldData data, int type) { - Name = name; - Meta = meta; + Name = data.Name; + Meta = data.Meta; + Ref = data.Ref; Type = type; } } @@ -58,15 +60,16 @@ namespace refl data.FieldList.Clear(); foreach (var field in pair.Value.MemberList) { - data.FieldList.Add(new FieldMetaData(field.Name, field.Meta, 1)); + data.FieldList.Add(new FieldMetaData(field, 1)); } foreach (var field in pair.Value.CtorList) { - data.FieldList.Add(new FieldMetaData(field.Name, field.Meta, 2)); + data.FieldList.Add(new FieldMetaData(field, 2)); } foreach (var field in pair.Value.MethodList) { - data.FieldList.Add(new FieldMetaData(field.Name, field.Meta, 3)); + int type = string.IsNullOrEmpty(field.Ref) ? 3 : 4; + data.FieldList.Add(new FieldMetaData(field, type)); } data.MemberCount = pair.Value.MemberList.Count; data.CtorCount = pair.Value.CtorList.Count; diff --git a/src/refl/MetaToken.cs b/src/refl/MetaToken.cs index 61d0293..4187029 100644 --- a/src/refl/MetaToken.cs +++ b/src/refl/MetaToken.cs @@ -3,7 +3,6 @@ namespace refl { internal class MetaToken { - /* static bool IsMatching(char left, char right) { return (left == '(' && right == ')') || @@ -15,49 +14,51 @@ namespace refl public static int FindTokenIndex(string line) { Stack stack = new Stack(); - for(int i = 0, l = line.Length;i < l; i++) + for (int i = 0, l = line.Length; i < l; i++) { var c = line[i]; if (c == ',' && stack.Count == 0) { return i; } - if(stack.Count > 0 && IsMatching(stack.Peek(), c)) + if (stack.Count > 0 && IsMatching(stack.Peek(), c)) { stack.Pop(); - }else if(c == '(' || c == '{' || c == '[' || c =='"' || c == '\'') + } + else if (c == '(' || c == '{' || c == '[' || c == '"' || c == '\'') { stack.Push(c); } } return -1; } - public static void ParseMeta(string line, out string key, out string value) + public static bool ParseAllMeta(string line, out string key, out string value, out string? next) { int index = FindTokenIndex(line); if (index == -1) { - key = line; - value = "{}"; + ParseMeta(line, out key, out value); + next = null; } else { - key = line.Substring(0, index); - value = '{' + line.Substring(index + 1) + '}'; + ParseMeta(line.Substring(0, index), out key, out value); + next = line.Substring(index + 1); } - }*/ + return index != -1; + } public static void ParseMeta(string line, out string key, out string value) { - if (line.Contains(',')) + if (line.Contains('=')) { - var res = line.Split(',', 2); - key = res[0]; - value = '{' + res[1] + '}'; + var res = line.Split('=', 2); + key = res[0].Trim(); + value = res[1]; } else { key = line; - value = "{}"; + value = ""; } } } diff --git a/src/refl/OverTree.cs b/src/refl/OverTree.cs new file mode 100644 index 0000000..143dfb8 --- /dev/null +++ b/src/refl/OverTree.cs @@ -0,0 +1,74 @@ +using CppAst; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace refl +{ + internal class OverTree + { + public const int PrefixSize = 6; + List Ctors = new List(); + List Funcs = new List(); + private bool isInit = false; + public OverTree() { } + public void Init(CppClass cppClass) + { + if (isInit) + { + return; + } + isInit = true; + foreach (var types in cppClass.Typedefs) + { + string key = types.Name.Substring(0, PrefixSize); + if(key == "__Ctor") + { + Ctors.Add(int.Parse(types.Name.Substring(PrefixSize))); + } + else if(key == "__Func") + { + Funcs.Add(int.Parse(types.Name.Substring(PrefixSize))); + } + } + Ctors.Sort(); + Funcs.Sort(); + } + public void Clear() + { + Ctors.Clear(); + Funcs.Clear(); + isInit = false; + } + public string Find(string name) + { + string key = name.Substring(0, PrefixSize); + int v = int.Parse(name.Substring(PrefixSize)); + if (key == "__Ctor") + { + v = FindValue(Ctors, v); + } + else + { + v = FindValue(Funcs, v); + } + return key + v; + } + private static int FindValue(List sortedNumbers, int target) + { + if(sortedNumbers.Count == 0) + { + return target; + } + int index = sortedNumbers.BinarySearch(target); + if(index < 0) + { + index = ~index; + } + index = index > 0 ? index - 1 : 0; + return sortedNumbers[index]; + } + } +} \ No newline at end of file diff --git a/src/refl/_install.bat b/src/refl/_install.bat new file mode 100644 index 0000000..dd9c6eb --- /dev/null +++ b/src/refl/_install.bat @@ -0,0 +1,6 @@ +@echo off +set "source_dir=%CD%" REM 当前目录 +set "destination_dir=F:\ouczbs\zengine\tools\refl" REM 指定目标目录 +xcopy "%source_dir%\bin\Release\net8.0\win-x64\*" "%destination_dir%\" /Y +xcopy "%source_dir%\template\*" "%destination_dir%\template\" /Y +pause \ No newline at end of file diff --git a/src/refl/cpp/macro.h b/src/refl/cpp/macro.h index 6604def..968967e 100644 --- a/src/refl/cpp/macro.h +++ b/src/refl/cpp/macro.h @@ -3,28 +3,29 @@ #define __cppast(...) #endif -#define __Meta(...) __cppast(Meta,__VA_ARGS__) +#define __Meta(...) __cppast(Meta=__VA_ARGS__) #define UPROPERTY(...) __Meta(__VA_ARGS__) #define UFUNCTION(...) __Meta(__VA_ARGS__) -#define __vkMeta(...) __cppast(vkMeta,__VA_ARGS__) +#define __vkMeta(...) __cppast(vkMeta=__VA_ARGS__) #define UPROPERTY_vk(...) __vkMeta(__VA_ARGS__) #define UFUNCTION_vk(...) __vkMeta(__VA_ARGS__) -#define __dxMeta(...) __cppast(dxMeta,__VA_ARGS__) +#define __dxMeta(...) __cppast(dxMeta=__VA_ARGS__) #define UPROPERTY_dx(...) __dxMeta(__VA_ARGS__) #define UFUNCTION_dx(...) __dxMeta(__VA_ARGS__) // 辅助宏,用于实际拼接 #define CONCATENATE(arg1, arg2) CONCATENATE_IMPL(arg1, arg2) #define CONCATENATE_IMPL(arg1, arg2) arg1##arg2 -#define UNIQUE_NAME(base) CONCATENATE(base, __LINE__) +#define MY_UNIQUE_NAME(base) CONCATENATE(base, __LINE__) -#define OVERLOAD_CTOR_IMPL(Class, ...) using UNIQUE_NAME(__Ctor) = Class(*)(__VA_ARGS__); -#define OVERLOAD_FUNC_IMPL(Func, R, ...) using UNIQUE_NAME(__Func) = R(*)(__VA_ARGS__); +#define USING_CTOR_NAME MY_UNIQUE_NAME(__Ctor) +#define USING_FUNC_NAME MY_UNIQUE_NAME(__Func) -#define OVERLOAD_CTOR(Class, ...) OVERLOAD_CTOR_IMPL(Class, __VA_ARGS__);Class(__VA_ARGS__) -#define OVERLOAD_FUNC(Func, R, ...) OVERLOAD_FUNC_IMPL(Func, R, __VA_ARGS__);R Func(__VA_ARGS__) +#define USING_OVERLOAD_CTOR(Class, ...) using USING_CTOR_NAME = Class(*)(__VA_ARGS__); +#define USING_OVERLOAD_FUNC(R, ...) using USING_FUNC_NAME = R(*)(__VA_ARGS__); +#define USING_OVERLOAD_CLASS_FUNC(R, Class, ...) using USING_FUNC_NAME = R(Class::*)(__VA_ARGS__); namespace refl_impl { struct Meta {}; diff --git a/src/refl/cpp/vertex.h b/src/refl/cpp/vertex.h index 1aa2261..d1c58c5 100644 --- a/src/refl/cpp/vertex.h +++ b/src/refl/cpp/vertex.h @@ -1,21 +1,16 @@ #include "refl/refl.h" -#include +#include +#include +#include +using std::string; +using std::vector; + using std::string_view; -namespace engineapi { - namespace test { - struct vec1 { - UPROPERTY({}) - int x; - UPROPERTY({}) - int y; - }; - } +namespace test { struct Guid { - UPROPERTY_vk({}) UPROPERTY({}) unsigned int Data1; - UPROPERTY_vk({}) UPROPERTY({}) unsigned short Data2; UPROPERTY({}) @@ -25,8 +20,10 @@ namespace engineapi { constexpr Guid() noexcept : Data1{ 0 }, Data2{ 0 }, Data3{ 0 }, Data4{ 0,0,0,0,0,0,0,0 } {} - UFUNCTION({}) - Guid(const string_view& str) noexcept + + USING_OVERLOAD_CTOR(Guid, const string_view&) + UFUNCTION({}, ref = USING_CTOR_NAME) + Guid(const std::string_view& str) noexcept : Guid{} { sscanf_s(str.data(), @@ -56,13 +53,17 @@ namespace engineapi { { return *reinterpret_cast(this) != GUID_NULL; } + USING_OVERLOAD_CLASS_FUNC(void, Guid, int) + UFUNCTION({}, ref = USING_FUNC_NAME) + void test(int x) { - operator string() const - { - return ToString(); } - UFUNCTION({}) - string ToString() const + USING_OVERLOAD_FUNC(void, Guid, float) + UFUNCTION({}, ref = USING_FUNC_NAME) + void test(float x) { + + } + operator std::string() const { char guid_cstr[39]; snprintf(guid_cstr, sizeof(guid_cstr), @@ -70,45 +71,16 @@ namespace engineapi { Data1, Data2, Data3, Data4[0], Data4[1], Data4[2], Data4[3], Data4[4], Data4[5], Data4[6], Data4[7]); - return string{ guid_cstr }; + return std::string{ guid_cstr }; } - UFUNCTION({}) static Guid Make() { Guid guid; const auto res = CoCreateGuid((GUID*)&guid); return guid; } + }; } -namespace work { -#include -#include - struct Guid2 { - - }; - struct Guid { - using __Ctor_1 = Guid (*)(const std::string_view, Guid2); - Guid(const std::string_view& str, Guid2) { - // Construct Guid from string_view (implementation to be added) - std::cout << "Guid constructed with: " << str << std::endl; - } - }; -} -namespace meta { - template - static T Ctor(Args... args) { - T obj(args...); // Construct object of type T (in this case, Guid) - return obj - } - template - static T(*)(Args...) CtorField() { - return &Ctor; - } - void create_guid() { - using work::Guid; - Guid::__Ctor_1* c1 = CtorField(); - //...其他逻辑 - } -} \ No newline at end of file +#include "guid_gen.inl" \ No newline at end of file diff --git a/src/refl/template/meta.liquid b/src/refl/template/meta.liquid index 9d93770..b2eeb91 100644 --- a/src/refl/template/meta.liquid +++ b/src/refl/template/meta.liquid @@ -6,9 +6,11 @@ {{ Indent }} {%- if field.Type == 1 %} {{ Indent }} refl::StaticMemberField(&T::{{field.Name}}, FName("{{field.Name}}"), {{field.Meta}}), {{ Indent }} {%- elsif field.Type == 2 %} -{{ Indent }} refl::StaticCtorField<{{field.Name}}>({{field.Meta}}), -{{ Indent }} {%- else %} +{{ Indent }} refl::StaticCtorField({{field.Meta}}), +{{ Indent }} {%- elsif field.Type == 3 %} {{ Indent }} refl::StaticMethodField(&T::{{field.Name}}, FName("{{field.Name}}"), {{field.Meta}}), +{{ Indent }} {%- else %} +{{ Indent }} refl::StaticMethodField((T::{{field.Ref}})&T::{{field.Name}}, FName("{{field.Name}}"), {{field.Meta}}), {{ Indent }} {%- endif %} {{ Indent }} {%- endfor %} {{ Indent }} }; @@ -40,9 +42,11 @@ {{ Indent }} {%- if field.Type == 1 %} {{ Indent }} MemberField(&T::{{field.Name}}, FName("{{field.Name}}"), memory, {{field.Meta}}), {{ Indent }} {%- elsif field.Type == 2 %} -{{ Indent }} CtorField<{{field.Name}}>(memory, {{field.Meta}}), -{{ Indent }} {%- else %} +{{ Indent }} CtorField(memory, {{field.Meta}}), +{{ Indent }} {%- elsif field.Type == 3 %} {{ Indent }} MethodField(&T::{{field.Name}}, FName("{{field.Name}}"), memory, {{field.Meta}}), +{{ Indent }} {%- else %} +{{ Indent }} MethodField((T::{{field.Ref}})&T::{{field.Name}}, FName("{{field.Name}}"), memory, {{field.Meta}}), {{ Indent }} {%- endif %} {{ Indent }} {%- endfor %} {{ Indent }} };