refl support overload
This commit is contained in:
parent
e4bba053cc
commit
6d4d39ee4e
@ -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<string, string> UserMeta = new Dictionary<string, string>();
|
||||
public FieldData(string name, string meta)
|
||||
{
|
||||
Name = name;
|
||||
Meta = meta;
|
||||
Meta = "{" + meta + "}";
|
||||
Ref = "";
|
||||
}
|
||||
|
||||
}
|
||||
@ -48,6 +52,8 @@ namespace refl
|
||||
public string NameSpace { get; set; }
|
||||
public List<ClassMeta> ClassList;
|
||||
public List<ModuleMeta> 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<string> nameList = new List<string>{ "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,16 +118,36 @@ 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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -3,7 +3,6 @@ namespace refl
|
||||
{
|
||||
internal class MetaToken
|
||||
{
|
||||
/*
|
||||
static bool IsMatching(char left, char right)
|
||||
{
|
||||
return (left == '(' && right == ')') ||
|
||||
@ -25,39 +24,41 @@ namespace refl
|
||||
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 = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
74
src/refl/OverTree.cs
Normal file
74
src/refl/OverTree.cs
Normal 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
6
src/refl/_install.bat
Normal 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
|
||||
@ -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 {};
|
||||
|
||||
@ -1,21 +1,16 @@
|
||||
#include "refl/refl.h"
|
||||
#include <objbase.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
using std::string_view;
|
||||
namespace engineapi {
|
||||
namespace test {
|
||||
struct vec1 {
|
||||
UPROPERTY({})
|
||||
int x;
|
||||
UPROPERTY({})
|
||||
int y;
|
||||
};
|
||||
}
|
||||
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<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({})
|
||||
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 <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>();
|
||||
//...其他逻辑
|
||||
}
|
||||
}
|
||||
#include "guid_gen.inl"
|
||||
@ -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<T::{{field.Ref}}>({{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<T::{{field.Ref}}>(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 }} };
|
||||
|
||||
Loading…
Reference in New Issue
Block a user