refl support overload

This commit is contained in:
ouczbs 2024-06-21 22:20:13 +08:00
parent e4bba053cc
commit 6d4d39ee4e
8 changed files with 189 additions and 103 deletions

View File

@ -1,5 +1,7 @@
using CppAst; using CppAst;
using Irony; using Irony;
using static System.Net.Mime.MediaTypeNames;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace refl namespace refl
{ {
@ -7,11 +9,13 @@ namespace refl
{ {
public string Name { get; set; } public string Name { get; set; }
public string Meta { get; set; } public string Meta { get; set; }
public string Ref { get; set; }
//public Dictionary<string, string> UserMeta = new Dictionary<string, string>();
public FieldData(string name, string meta) public FieldData(string name, string meta)
{ {
Name = name; Name = name;
Meta = meta; Meta = "{" + meta + "}";
Ref = "";
} }
} }
@ -46,8 +50,10 @@ namespace refl
{ {
public static HashSet<string> NameSet = new HashSet<string>(); public static HashSet<string> NameSet = new HashSet<string>();
public string NameSpace { get; set; } public string NameSpace { get; set; }
public List<ClassMeta> ClassList; public List<ClassMeta> ClassList;
public List<ModuleMeta> ChildList; public List<ModuleMeta> ChildList;
public static OverTree OverData = new OverTree();
public ModuleMeta(string name_space) public ModuleMeta(string name_space)
{ {
NameSpace = name_space; NameSpace = name_space;
@ -71,6 +77,7 @@ namespace refl
} }
} }
ClassMeta cls_meta = new ClassMeta(cppClass.Name, parentName); ClassMeta cls_meta = new ClassMeta(cppClass.Name, parentName);
OverData.Clear();
foreach (var field in cppClass.Fields) foreach (var field in cppClass.Fields)
{ {
if (field.Attributes.Count == 0) if (field.Attributes.Count == 0)
@ -93,17 +100,15 @@ namespace refl
foreach (var attribute in func.Attributes) foreach (var attribute in func.Attributes)
{ {
string key, value; 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)) if (!cls_meta.Fields.ContainsKey(key))
{ {
cls_meta.Fields.Add(key, new FieldMeta()); cls_meta.Fields.Add(key, new FieldMeta());
} }
List<string> nameList = new List<string>{ "T" }; cls_meta.Fields[key].CtorList.Add(data);
foreach (var parm in func.Parameters) ParseClassUserMeta(cppClass, data, next);
{
nameList.Add(parm.Type.FullName);
}
cls_meta.Fields[key].CtorList.Add(new FieldData(string.Join(",", nameList), value));
} }
} }
foreach (var func in cppClass.Functions) foreach (var func in cppClass.Functions)
@ -113,23 +118,43 @@ namespace refl
foreach (var attribute in func.Attributes) foreach (var attribute in func.Attributes)
{ {
string key, value; 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)) if (!cls_meta.Fields.ContainsKey(key))
{ {
cls_meta.Fields.Add(key, new FieldMeta()); 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; 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) public static ModuleMeta ParseCppNamespaces(CppNamespace cpp)
{ {
var module = new ModuleMeta(cpp.Name); var module = new ModuleMeta(cpp.Name);
foreach (var cppClass in cpp.Classes) foreach (var cppClass in cpp.Classes)
{ {
var cls_meta = ParseCppClass(cppClass); var cls_meta = ParseCppClass(cppClass);
if(cls_meta.Fields.Count > 0) if (cls_meta.Fields.Count > 0)
{ {
module.ClassList.Add(cls_meta); module.ClassList.Add(cls_meta);
} }
@ -137,7 +162,7 @@ namespace refl
foreach (var spaces in cpp.Namespaces) foreach (var spaces in cpp.Namespaces)
{ {
var child = ParseCppNamespaces(spaces); 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); module.ChildList.Add(child);
} }
@ -150,12 +175,12 @@ namespace refl
foreach (var cppClass in cpp.Classes) foreach (var cppClass in cpp.Classes)
{ {
var cls_meta = ParseCppClass(cppClass); var cls_meta = ParseCppClass(cppClass);
if(cls_meta.Fields.Count > 0) if (cls_meta.Fields.Count > 0)
{ {
module.ClassList.Add(cls_meta); module.ClassList.Add(cls_meta);
} }
} }
foreach(var spaces in cpp.Namespaces) foreach (var spaces in cpp.Namespaces)
{ {
var child = ParseCppNamespaces(spaces); var child = ParseCppNamespaces(spaces);
module.ChildList.Add(child); module.ChildList.Add(child);
@ -166,16 +191,16 @@ namespace refl
public static void ParseMetaName(ModuleMeta module) public static void ParseMetaName(ModuleMeta module)
{ {
ParseClassMetaName(module); ParseClassMetaName(module);
foreach(var child in module.ChildList) foreach (var child in module.ChildList)
{ {
ParseMetaName(child); ParseMetaName(child);
} }
} }
public static void ParseClassMetaName(ModuleMeta module) 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)) if (!NameSet.Contains(field.Key))
{ {

View File

@ -9,12 +9,14 @@ namespace refl
{ {
public string Name { get; set; } public string Name { get; set; }
public string Meta { get; set; } public string Meta { get; set; }
public string Ref { get; set; }
public int Type { get; set; } public int Type { get; set; }
public FieldMetaData(string name, string meta, int type) public FieldMetaData(FieldData data, int type)
{ {
Name = name; Name = data.Name;
Meta = meta; Meta = data.Meta;
Ref = data.Ref;
Type = type; Type = type;
} }
} }
@ -58,15 +60,16 @@ namespace refl
data.FieldList.Clear(); data.FieldList.Clear();
foreach (var field in pair.Value.MemberList) 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) 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) 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.MemberCount = pair.Value.MemberList.Count;
data.CtorCount = pair.Value.CtorList.Count; data.CtorCount = pair.Value.CtorList.Count;

View File

@ -3,7 +3,6 @@ namespace refl
{ {
internal class MetaToken internal class MetaToken
{ {
/*
static bool IsMatching(char left, char right) static bool IsMatching(char left, char right)
{ {
return (left == '(' && right == ')') || return (left == '(' && right == ')') ||
@ -15,49 +14,51 @@ namespace refl
public static int FindTokenIndex(string line) public static int FindTokenIndex(string line)
{ {
Stack<char> stack = new Stack<char>(); Stack<char> stack = new Stack<char>();
for(int i = 0, l = line.Length;i < l; i++) for (int i = 0, l = line.Length; i < l; i++)
{ {
var c = line[i]; var c = line[i];
if (c == ',' && stack.Count == 0) if (c == ',' && stack.Count == 0)
{ {
return i; return i;
} }
if(stack.Count > 0 && IsMatching(stack.Peek(), c)) if (stack.Count > 0 && IsMatching(stack.Peek(), c))
{ {
stack.Pop(); stack.Pop();
}else if(c == '(' || c == '{' || c == '[' || c =='"' || c == '\'') }
else if (c == '(' || c == '{' || c == '[' || c == '"' || c == '\'')
{ {
stack.Push(c); stack.Push(c);
} }
} }
return -1; 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); int index = FindTokenIndex(line);
if (index == -1) if (index == -1)
{ {
key = line; ParseMeta(line, out key, out value);
value = "{}"; next = null;
} }
else else
{ {
key = line.Substring(0, index); ParseMeta(line.Substring(0, index), out key, out value);
value = '{' + line.Substring(index + 1) + '}'; next = line.Substring(index + 1);
} }
}*/ return index != -1;
}
public static void ParseMeta(string line, out string key, out string value) public static void ParseMeta(string line, out string key, out string value)
{ {
if (line.Contains(',')) if (line.Contains('='))
{ {
var res = line.Split(',', 2); var res = line.Split('=', 2);
key = res[0]; key = res[0].Trim();
value = '{' + res[1] + '}'; value = res[1];
} }
else else
{ {
key = line; key = line;
value = "{}"; value = "";
} }
} }
} }

74
src/refl/OverTree.cs Normal file
View File

@ -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<int> Ctors = new List<int>();
List<int> Funcs = new List<int>();
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<int> 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];
}
}
}

6
src/refl/_install.bat Normal file
View File

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

View File

@ -3,28 +3,29 @@
#define __cppast(...) #define __cppast(...)
#endif #endif
#define __Meta(...) __cppast(Meta,__VA_ARGS__) #define __Meta(...) __cppast(Meta=__VA_ARGS__)
#define UPROPERTY(...) __Meta(__VA_ARGS__) #define UPROPERTY(...) __Meta(__VA_ARGS__)
#define UFUNCTION(...) __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 UPROPERTY_vk(...) __vkMeta(__VA_ARGS__)
#define UFUNCTION_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 UPROPERTY_dx(...) __dxMeta(__VA_ARGS__)
#define UFUNCTION_dx(...) __dxMeta(__VA_ARGS__) #define UFUNCTION_dx(...) __dxMeta(__VA_ARGS__)
// 辅助宏,用于实际拼接 // 辅助宏,用于实际拼接
#define CONCATENATE(arg1, arg2) CONCATENATE_IMPL(arg1, arg2) #define CONCATENATE(arg1, arg2) CONCATENATE_IMPL(arg1, arg2)
#define CONCATENATE_IMPL(arg1, arg2) 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 USING_CTOR_NAME MY_UNIQUE_NAME(__Ctor)
#define OVERLOAD_FUNC_IMPL(Func, R, ...) using UNIQUE_NAME(__Func) = R(*)(__VA_ARGS__); #define USING_FUNC_NAME MY_UNIQUE_NAME(__Func)
#define OVERLOAD_CTOR(Class, ...) OVERLOAD_CTOR_IMPL(Class, __VA_ARGS__);Class(__VA_ARGS__) #define USING_OVERLOAD_CTOR(Class, ...) using USING_CTOR_NAME = Class(*)(__VA_ARGS__);
#define OVERLOAD_FUNC(Func, R, ...) OVERLOAD_FUNC_IMPL(Func, R, __VA_ARGS__);R Func(__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 { namespace refl_impl {
struct Meta {}; struct Meta {};

View File

@ -1,21 +1,16 @@
#include "refl/refl.h" #include "refl/refl.h"
#include <objbase.h> #include <objbase.h>
#include <string>
#include <vector>
using std::string;
using std::vector;
using std::string_view; using std::string_view;
namespace engineapi { namespace test {
namespace test {
struct vec1 {
UPROPERTY({})
int x;
UPROPERTY({})
int y;
};
}
struct Guid struct Guid
{ {
UPROPERTY_vk({})
UPROPERTY({}) UPROPERTY({})
unsigned int Data1; unsigned int Data1;
UPROPERTY_vk({})
UPROPERTY({}) UPROPERTY({})
unsigned short Data2; unsigned short Data2;
UPROPERTY({}) UPROPERTY({})
@ -25,8 +20,10 @@ namespace engineapi {
constexpr Guid() noexcept constexpr Guid() noexcept
: Data1{ 0 }, Data2{ 0 }, Data3{ 0 }, Data4{ 0,0,0,0,0,0,0,0 } : 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{} : Guid{}
{ {
sscanf_s(str.data(), sscanf_s(str.data(),
@ -56,13 +53,17 @@ namespace engineapi {
{ {
return *reinterpret_cast<const GUID*>(this) != GUID_NULL; return *reinterpret_cast<const GUID*>(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({}) USING_OVERLOAD_FUNC(void, Guid, float)
string ToString() const UFUNCTION({}, ref = USING_FUNC_NAME)
void test(float x) {
}
operator std::string() const
{ {
char guid_cstr[39]; char guid_cstr[39];
snprintf(guid_cstr, sizeof(guid_cstr), snprintf(guid_cstr, sizeof(guid_cstr),
@ -70,45 +71,16 @@ namespace engineapi {
Data1, Data2, Data3, Data1, Data2, Data3,
Data4[0], Data4[1], Data4[2], Data4[3], Data4[0], Data4[1], Data4[2], Data4[3],
Data4[4], Data4[5], Data4[6], Data4[7]); Data4[4], Data4[5], Data4[6], Data4[7]);
return string{ guid_cstr }; return std::string{ guid_cstr };
} }
UFUNCTION({})
static Guid Make() static Guid Make()
{ {
Guid guid; Guid guid;
const auto res = CoCreateGuid((GUID*)&guid); const auto res = CoCreateGuid((GUID*)&guid);
return guid; return guid;
} }
}; };
} }
namespace work { #include "guid_gen.inl"
#include <iostream>
#include <string_view>
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<typename T, typename... Args>
static T Ctor(Args... args) {
T obj(args...); // Construct object of type T (in this case, Guid)
return obj
}
template<typename T, typename... Args>
static T(*)(Args...) CtorField() {
return &Ctor<T, Args...>;
}
void create_guid() {
using work::Guid;
Guid::__Ctor_1* c1 = CtorField<Guid::__Ctor_1>();
//...其他逻辑
}
}

View File

@ -6,9 +6,11 @@
{{ Indent }} {%- if field.Type == 1 %} {{ Indent }} {%- if field.Type == 1 %}
{{ Indent }} refl::StaticMemberField(&T::{{field.Name}}, FName("{{field.Name}}"), {{field.Meta}}), {{ Indent }} refl::StaticMemberField(&T::{{field.Name}}, FName("{{field.Name}}"), {{field.Meta}}),
{{ Indent }} {%- elsif field.Type == 2 %} {{ Indent }} {%- elsif field.Type == 2 %}
{{ Indent }} refl::StaticCtorField<{{field.Name}}>({{field.Meta}}), {{ Indent }} refl::StaticCtorField<T::{{field.Ref}}>({{field.Meta}}),
{{ Indent }} {%- else %} {{ Indent }} {%- elsif field.Type == 3 %}
{{ Indent }} refl::StaticMethodField(&T::{{field.Name}}, FName("{{field.Name}}"), {{field.Meta}}), {{ 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 }} {%- endif %}
{{ Indent }} {%- endfor %} {{ Indent }} {%- endfor %}
{{ Indent }} }; {{ Indent }} };
@ -40,9 +42,11 @@
{{ Indent }} {%- if field.Type == 1 %} {{ Indent }} {%- if field.Type == 1 %}
{{ Indent }} MemberField(&T::{{field.Name}}, FName("{{field.Name}}"), memory, {{field.Meta}}), {{ Indent }} MemberField(&T::{{field.Name}}, FName("{{field.Name}}"), memory, {{field.Meta}}),
{{ Indent }} {%- elsif field.Type == 2 %} {{ Indent }} {%- elsif field.Type == 2 %}
{{ Indent }} CtorField<{{field.Name}}>(memory, {{field.Meta}}), {{ Indent }} CtorField<T::{{field.Ref}}>(memory, {{field.Meta}}),
{{ Indent }} {%- else %} {{ Indent }} {%- elsif field.Type == 3 %}
{{ Indent }} MethodField(&T::{{field.Name}}, FName("{{field.Name}}"), memory, {{field.Meta}}), {{ 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 }} {%- endif %}
{{ Indent }} {%- endfor %} {{ Indent }} {%- endfor %}
{{ Indent }} }; {{ Indent }} };