From 6566f11269990411bed6e9ad839533fd3220385f Mon Sep 17 00:00:00 2001 From: tqcq <99722391+tqcq@users.noreply.github.com> Date: Tue, 5 Mar 2024 00:13:53 +0800 Subject: [PATCH] feat support reflection --- 3rdparty/sled | 2 +- CMakeLists.txt | 2 + runtime/apply.h | 60 ------------ runtime/reflection.gen.cc | 5 + runtime/reflection.h | 141 +++++++++++++++++++++++----- runtime/test.gen.cc | 90 ++++++++++++++++++ runtime/test.gen.h | 41 ++++++++ runtime/test.h | 33 ++----- src/clang/parser.cc | 1 + src/generators/base_generator.cc | 25 ++++- src/main.cc | 151 ++++++++++++++---------------- src/types/field.cc | 12 +++ src/types/field.h | 2 + src/types/method.cc | 6 ++ src/types/method.h | 1 + template/class_proxy_include.inja | 25 +++-- template/class_proxy_source.inja | 96 +++++++++++++------ 17 files changed, 462 insertions(+), 231 deletions(-) delete mode 100644 runtime/apply.h create mode 100644 runtime/reflection.gen.cc create mode 100644 runtime/test.gen.cc create mode 100644 runtime/test.gen.h diff --git a/3rdparty/sled b/3rdparty/sled index fcce112..4402688 160000 --- a/3rdparty/sled +++ b/3rdparty/sled @@ -1 +1 @@ -Subproject commit fcce11249be00ca0c7f8c2e75938de4b3e5f26da +Subproject commit 4402688c9c63e9885de1bf99cd718150b036ac7a diff --git a/CMakeLists.txt b/CMakeLists.txt index c34d37d..2836b76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,8 @@ add_executable(meta src/types/field.cc src/types/method.cc src/registry.cc + runtime/test.gen.cc + runtime/reflection.gen.cc ) ### add clang diff --git a/runtime/apply.h b/runtime/apply.h deleted file mode 100644 index 5b11168..0000000 --- a/runtime/apply.h +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once -#ifndef META_APPLY_H -#define META_APPLY_H -#include -#include - -namespace meta { -namespace reflection { -namespace detail { -template -struct Sequence {}; - -template -struct MakeSeq : MakeSeq {}; - -template -struct MakeSeq<0, Seq...> { - using type = Sequence; -}; - -template -ReturnT -ApplyImpl(const Func &func, const Tuple &tuple, const Sequence &) -{ - return std::bind(func, std::get(tuple)...)(); -} - -struct VoidTag {}; - -}// namespace detail - -template::value, ReturnT>::type * = nullptr> -ReturnT -apply(const Func &func, const Tuple &tuple) -{ - return detail::ApplyImpl( - func, - tuple, - typename detail::MakeSeq::value>::type()); -} - -template::value, detail::VoidTag>::type * = nullptr> -ReturnT -apply(const Func &func, const Tuple &tuple) -{ - return detail::ApplyImpl( - func, - tuple, - typename detail::MakeSeq::value>::type()); -} - -}// namespace reflection -}// namespace meta -#endif// META_APPLY_H diff --git a/runtime/reflection.gen.cc b/runtime/reflection.gen.cc new file mode 100644 index 0000000..3355427 --- /dev/null +++ b/runtime/reflection.gen.cc @@ -0,0 +1,5 @@ +#include "test.gen.h" + +void ::meta::reflection::Registry::RegisterAll() { ::test::Test::Test_Class::Register(); } + +void ::meta::reflection::Registry::UnregisterAll() {} diff --git a/runtime/reflection.h b/runtime/reflection.h index 475a54a..c7b34fc 100644 --- a/runtime/reflection.h +++ b/runtime/reflection.h @@ -2,7 +2,6 @@ #ifndef META_RUNTIME_REFLECTION_H #define META_RUNTIME_REFLECTION_H #include "any.h" -#include "apply.h" #include #include #include @@ -42,7 +41,7 @@ RemoveTypeSpace(const std::string &str, const std::string &chars = "[]()<>*&:") } template::type> -std::string +inline std::string PrettyNameImpl() { const std::string name = typeid(U).name(); @@ -71,13 +70,20 @@ PrettyName() #define META(...) #define CLASS(class_name, ...) class class_name #define STRUCT(struct_name, ...) struct struct_name -#endif// __REFLECTION_PARSER_ +#endif// __REFLECTION_PARSER_ \ #define META_REFLECTION_BODY(class_name) \ - friend class meta::reflection::##class_name##_Method; \ - friend class meta::reflection::##class_name##_Field; \ - friend class meta::reflection::##class_name##_Constructor; \ - friend class meta::reflection::##class_name##_Serializer; + class class_name##_Class; \ + class class_name##_Constructor; \ + class class_name##_Method; \ + class class_name##_Field; \ + class class_name##_Serializer; \ + friend class class_name##_Class; \ + friend class class_name##_Constructor; \ + friend class class_name##_Method; \ + friend class class_name##_Field; \ + friend class class_name##_Serializer; \ + friend class ::meta::reflection::Registry; class Constructor; class Method; @@ -113,7 +119,7 @@ public: typename... Params> inline ReturnT InvokeAndCast(void *instance, Params &&...params) const { - return ::meta::reflection::any_cast(InvokeImpl(instance, {¶ms...})); + return ::meta::reflection::any_cast(InvokeImpl(instance, {params...})); } template inline void InvokeAndCast(void *instance, Params &&...params) const { - ::meta::reflection::any_cast(InvokeImpl(instance, {¶ms...})); + ::meta::reflection::any_cast(InvokeImpl(instance, {params...})); } template inline ::meta::reflection::any Invoke(void *instance, Params &&...params) const { - return InvokeImpl(instance, {¶ms...}); + return InvokeImpl(instance, {params...}); } protected: - virtual ::meta::reflection::any InvokeImpl(void *instance, - const std::vector ¶ms) const + virtual ::meta::reflection::any + InvokeImpl(void *instance, const std::vector<::meta::reflection::any> ¶ms) const = 0; private: @@ -167,23 +173,106 @@ public: Class(const std::string &name, std::shared_ptr base_class = nullptr) : BaseType(name, base_class) {} + + inline std::vector> GetBaseClasses() const { return base_classes_; } + + inline std::shared_ptr GetBaseClass(const std::string &name) const + { + auto iter = base_class_by_name_.find(name); + if (iter != base_class_by_name_.end()) { return iter->second; } + return nullptr; + } + + inline std::vector> GetMethods() const { return methods_; } + + inline std::shared_ptr GetMethod(const std::string &name) const + { + auto iter = method_by_name_.find(name); + if (iter != method_by_name_.end()) { return iter->second; } + return nullptr; + } + + inline std::vector> GetFields() const { return fields_; } + + inline std::shared_ptr GetField(const std::string &name) const + { + auto iter = field_by_name_.find(name); + if (iter != field_by_name_.end()) { return iter->second; } + return nullptr; + } + +protected: + void AddBaseClass(std::shared_ptr clz) + { + if (base_class_by_name_.find(clz->Name()) != base_class_by_name_.end()) { return; } + base_classes_.push_back(clz); + base_class_by_name_[clz->Name()] = clz; + } + + void AddMethod(std::shared_ptr method) + { + if (method_by_name_.find(method->Name()) != method_by_name_.end()) { return; } + methods_.push_back(method); + method_by_name_[method->Name()] = method; + } + + void AddField(std::shared_ptr field) + { + fields_.push_back(field); + field_by_name_[field->Name()] = field; + } + +private: + std::unordered_map> base_class_by_name_; + std::unordered_map> method_by_name_; + std::unordered_map> field_by_name_; + + std::vector> base_classes_; + std::vector> methods_; + std::vector> fields_; }; -#define REFLECTION_BODY() \ - friend class meta::Serializer; \ - friend class meta::Class; \ - friend class meta::Method; \ - friend class meta::Field; \ - friend class meta::Constructor; - -class Reflectioin { +class Registry { public: - static Reflectioin *Instance(); - ~Reflectioin(); - std::shared_ptr GetClass(); - // std::shared_ptr GetConstructor(std::shared_ptr clz); - std::shared_ptr GetMethod(std::shared_ptr clz); - std::shared_ptr GetField(std::shared_ptr clz); + static Registry *Instance() + { + static Registry instance; + return &instance; + } + + ~Registry() {} + + static void RegisterAll(); + static void UnregisterAll(); + + static std::shared_ptr GetClass(const std::string &name) + { + return Instance()->GetClassInner(name); + } + + static void RegisterClass(std::shared_ptr clz) { Instance()->RegisterClassInner(clz); } + + static std::vector> GetClasses() { return Instance()->classes(); } + +private: + std::shared_ptr GetClassInner(const std::string &name) const + { + auto iter = class_by_name_.find(name); + if (iter != class_by_name_.end()) { return iter->second; } + return nullptr; + } + + inline void RegisterClassInner(std::shared_ptr clz) + { + if (class_by_name_.find(clz->Name()) != class_by_name_.end()) { return; } + classes_.push_back(clz); + class_by_name_[clz->Name()] = clz; + } + + inline std::vector> classes() const { return classes_; } + + std::unordered_map> class_by_name_; + std::vector> classes_; }; }// namespace reflection diff --git a/runtime/test.gen.cc b/runtime/test.gen.cc new file mode 100644 index 0000000..f55438d --- /dev/null +++ b/runtime/test.gen.cc @@ -0,0 +1,90 @@ +#include "test.gen.h" +#include + +/** + * Class + **/ +test::Test::Test_Class::Test_Class() +: ::meta::reflection::Class("test::Test", nullptr) +{ +} + +void test::Test::Test_Class::Register() { + auto self = new test::Test::Test_Class(); + auto clz = std::shared_ptr<::meta::reflection::Class>(self); + // self->AddBaseClassProxy(); + + self->AddMethod(std::make_shared("size", clz)); + self->AddMethod(std::make_shared("length", clz)); + + self->AddField(std::make_shared("length_", clz)); + self->AddField(std::make_shared("size_", clz)); + + ::meta::reflection::Registry::Instance()->RegisterClass(clz); +} +void test::Test::Test_Class::AddBaseClassProxy(std::shared_ptr<::meta::reflection::Class> base) { + AddBaseClass(base); +} +void test::Test::Test_Class::AddMethodProxy(std::shared_ptr<::meta::reflection::Method> method) { + AddMethod(method); +} +void test::Test::Test_Class::AddFieldProxy(std::shared_ptr<::meta::reflection::Field> field) { + AddField(field); +} + + +/** + * Field + **/ + +test::Test::Test_Field::Test_Field( + const std::string& name, + std::shared_ptr<::meta::reflection::Class> parent) +: ::meta::reflection::Field(name, parent) {} + +::meta::reflection::any test::Test::Test_Field::GetImpl(void* instance) const { + ::test::Test* obj = (::test::Test*)instance; + + if (strcmp(Name().c_str(), "length_") == 0) { + return obj->length_; + } + if (strcmp(Name().c_str(), "size_") == 0) { + return obj->size_; + } + return ::meta::reflection::any{}; +} + +void test::Test::Test_Field::SetImpl(void* instance, const ::meta::reflection::any& value) const { + ::test::Test* obj = (::test::Test*)instance; + if(strcmp(Name().c_str(), "length_") == 0) { obj->length_ = ::meta::reflection::any_cast(value);} + if(strcmp(Name().c_str(), "size_") == 0) { obj->size_ = ::meta::reflection::any_cast(value);} +} + + + +/** + * Method + **/ +test::Test::Test_Method::Test_Method( + const std::string& name, + std::shared_ptr<::meta::reflection::Class> parent) +: ::meta::reflection::Method(name, parent) {} + +::meta::reflection::any test::Test::Test_Method::InvokeImpl(void* instance, const std::vector<::meta::reflection::any> ¶ms) const { + ::test::Test* obj = (::test::Test*)instance; + + if (strcmp(Name().c_str(), "size") == 0) { + return + obj-> +size( + ); + } + if (strcmp(Name().c_str(), "length") == 0) { + return + obj-> +length( + ); + } + return ::meta::reflection::any{}; +} + diff --git a/runtime/test.gen.h b/runtime/test.gen.h new file mode 100644 index 0000000..c1bc867 --- /dev/null +++ b/runtime/test.gen.h @@ -0,0 +1,41 @@ +#pragma once +#ifndef META_GEN_Test_PROXY_H +#define META_GEN_Test_PROXY_H + +#include "test.h" + +// namespace meta { +// namespace reflection { + +class ::test::Test::Test_Class : public ::meta::reflection::Class { +public: + Test_Class(); + static void Register(); +private: + void AddBaseClassProxy(std::shared_ptr<::meta::reflection::Class> base) ; + void AddMethodProxy(std::shared_ptr<::meta::reflection::Method> method) ; + void AddFieldProxy(std::shared_ptr<::meta::reflection::Field> field) ; +}; + +class ::test::Test::Test_Field : public ::meta::reflection::Field { +public: + Test_Field(const std::string& name, std::shared_ptr<::meta::reflection::Class> parent); + +protected: + ::meta::reflection::any GetImpl(void* instance) const override; + void SetImpl(void* instance, const ::meta::reflection::any& value) const override; +}; + +class ::test::Test::Test_Method : public ::meta::reflection::Method { +public: + Test_Method(const std::string& name, std::shared_ptr<::meta::reflection::Class> parent); + +protected: + ::meta::reflection::any InvokeImpl(void* instance, const std::vector<::meta::reflection::any> ¶ms) const override; +}; + +// } // namespace reflection +// } // namespace meta + +#endif // META_GEN_Test_PROXY_H + diff --git a/runtime/test.h b/runtime/test.h index 3dceaec..485d94a 100644 --- a/runtime/test.h +++ b/runtime/test.h @@ -3,38 +3,25 @@ #define META_RUNTIME_TEST_H #include "reflection.h" +#include namespace test { -class TypeDef {}; - CLASS(Test) { + META_REFLECTION_BODY(Test); + public: - META("Constructor") - Test() : b_(0), a_(0) {} + Test() {} - Test(int a) : b_(0), a_(a) {} - - META("Test") - int GetA() const { return a_; } - - int kk(int, void *); - TypeDef GetTypeDef() const { return type_def_; } + const size_t size() const { return size_; } + const size_t length() const { return length_; } private: - struct Void {}; + META("1") + int length_; - STRUCT(VoidMeta, "VoidMeta") - { - META("Enable") - int a; - }; - - const int b_; - int a_; - - META("TypeDef") - TypeDef type_def_; + META("2") + int size_; }; }// namespace test diff --git a/src/clang/parser.cc b/src/clang/parser.cc index e6f6537..a9f5d8e 100644 --- a/src/clang/parser.cc +++ b/src/clang/parser.cc @@ -59,6 +59,7 @@ Parser::Parse(const std::string &file_name, std::vector extra_args // ignore error for reflection.h if (sled::EndsWith(filename, "reflection.h")) { continue; } + if (sled::EndsWith(filename, "any.h")) { continue; } LOGE("parser", "diagnostic: {}", msg); } diff --git a/src/generators/base_generator.cc b/src/generators/base_generator.cc index 089c429..3349d7a 100644 --- a/src/generators/base_generator.cc +++ b/src/generators/base_generator.cc @@ -39,19 +39,38 @@ BaseGenerator::GenClassRenderData(Class *clz, inja::json &class_def) class_def["properties"] = inja::json::array(); for (auto &prop : clz->properties()) { class_def["properties"].push_back(prop); } + inja::json constructors = inja::json::array(); inja::json methods = inja::json::array(); inja::json fields = inja::json::array(); + GenClassConstructorRenderData(clz, constructors); GenClassMethodRenderData(clz, methods); GenClassFieldRenderData(clz, fields); + class_def["class_constructors"] = constructors; class_def["class_methods"] = methods; class_def["class_fields"] = fields; } void BaseGenerator::GenClassConstructorRenderData(Class *clz, inja::json &constructor_defs) -{} +{ + for (auto &constructor : clz->constructors()) { + inja::json constructor_def; + constructor_def["name"] = constructor->Name(); + constructor_def["properties"] = inja::json::array(); + for (auto &prop : constructor->properties()) { + constructor_def["properties"].push_back(prop); + } + inja::json params = inja::json::array(); + for (auto ¶m : constructor->arguments()) { + inja::json param_def; + param_def["name"] = ""; + param_def["type"] = param.GetDisplayName(); + params.push_back(param_def); + } + } +} void BaseGenerator::GenClassFieldRenderData(Class *clz, inja::json &field_defs) @@ -60,6 +79,7 @@ BaseGenerator::GenClassFieldRenderData(Class *clz, inja::json &field_defs) inja::json field_def; field_def["name"] = field->Name(); field_def["is_const"] = field->IsConst(); + field_def["is_static"] = field->IsStatic(); field_def["properties"] = inja::json::array(); for (auto &prop : field->properties()) { field_def["properties"].push_back(prop); } field_def["type"] = field->cursor().GetType().GetDisplayName(); @@ -73,9 +93,10 @@ BaseGenerator::GenClassMethodRenderData(Class *clz, inja::json &method_defs) for (auto &method : clz->methods()) { inja::json method_def; method_def["name"] = method->Name(); + method_def["is_const"] = method->IsConst(); + method_def["is_static"] = method->IsStatic(); method_def["properties"] = inja::json::array(); for (auto &prop : method->properties()) { method_def["properties"].push_back(prop); } - method_def["is_const"] = method->IsConst(); method_def["return_type"] = method->return_type().GetDisplayName(); inja::json params = inja::json::array(); for (auto ¶m : method->arguments()) { diff --git a/src/main.cc b/src/main.cc index c057c80..7ae8e95 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,6 +1,7 @@ #include "generators/base_generator.h" #include "reflection.h" #include "registry.h" +#include "test.gen.h" #include "types/class.h" #include "clang/parser.h" #include @@ -15,12 +16,13 @@ const char *kTag = "main"; class Generator : public meta::BaseGenerator { public: - Generator(const std::string &template_path) + Generator(const std::string &template_path, const std::string &output_path = "") { std::fstream in(template_path, std::ios::in); std::stringstream ss; ss << in.rdbuf(); template_ = ss.str(); + output_path_ = output_path; } ~Generator() override = default; @@ -33,9 +35,51 @@ public: inja::Environment env; env.set_trim_blocks(true); env.set_lstrip_blocks(true); + env.add_callback("to_upper", 1, [](inja::Arguments &args) { + return sled::ToUpper(args.at(0)->get()); + }); + env.add_callback("to_lower", 1, [](inja::Arguments &args) { + return sled::ToLower(args.at(0)->get()); + }); + // CamelCase or SnakeCase to SnakeCase + env.add_callback("to_snake_case", 1, [](inja::Arguments &args) { + const std::string str = args.at(0)->get(); + std::string result; + for (size_t i = 0; i < str.size(); i++) { + if (i > 0 && str[i] >= 'A' && str[i] <= 'Z') { result.push_back('_'); } + result.push_back(sled::ToLower(str[i])); + } + return result; + }); + env.add_callback("to_camel_case", 1, [](inja::Arguments &args) { + const std::string str = args.at(0)->get(); + std::string result; + bool to_upper = false; + for (size_t i = 0; i < str.size(); i++) { + if (str[i] == '_') { + to_upper = true; + } else { + if (to_upper) { + result.push_back(sled::ToUpper(str.substr(i, 1))[0]); + to_upper = false; + } else { + result.push_back(str[i]); + } + } + } + return result; + }); + try { LOGV(kTag, "data={}", class_def.dump()); - LOGV(kTag, "class_def={}", env.render(template_, class_def)); + std::string result = env.render(template_, class_def); + if (output_path_.empty()) { + LOGI(kTag, "render_result=\n{}", result); + } else { + std::ofstream out(output_path_); + out << result; + } + } catch (const std::exception &e) { LOGE(kTag, "error: {}", e.what()); } @@ -44,88 +88,14 @@ public: private: std::string template_; + std::string output_path_; }; -// template -// std::function -// MemberFunctionWrapper(void (ClassT::*func)(Args...)) -// { -// return [=](sled::any obj_args) { -// using tuple = ::std::tuple; -// // ::std::tuple *pTuple = ::sled::any_cast(obj_args); -// auto tuple_ptr = ::sled::any_cast(obj_args); -// sled::apply(func, *tuple_ptr); -// }; -// } - -template -std::function -MemberFunctionWrapper(ReturnT (ClassT::*func)(Args...)) -{ - return [=](sled::any obj_args) { - using tuple = ::std::tuple; - // ::std::tuple *pTuple = ::sled::any_cast(obj_args); - auto tuple_ptr = ::sled::any_cast(obj_args); - return sled::apply(func, *tuple_ptr); - }; -} - -class Test { -public: - void Show(int a, double b, std::string c) { LOGV(kTag, "a={}, b={}, c={}", a, b, c); } - - // int Show(int a, int b, const std::string &c) - // { - // LOGV(kTag, "a={}, b={}, c={}", a, b, c); - // return 0; - // } -}; - -class Adder { -public: - int Add(int a, int b) { return a + b; } - friend class meta::reflection::Method; -}; - -// Add(int, int) -class AdderMethod : public meta::reflection::Method { -public: - AdderMethod(const std::string &name, std::shared_ptr parent) - : meta::reflection::Method(name, parent) - { - fun_ = MemberFunctionWrapper(&Adder::Add); - } - - int Add(int a, int b) { return a + b; } - -protected: - meta::reflection::any InvokeImpl(void *instance, - const std::vector ¶ms) const override - { - Adder *adder = reinterpret_cast(instance); - using tuple = std::tuple; - auto t = std::make_tuple(adder, - *reinterpret_cast(params[0]), - *reinterpret_cast(params[1])); - return fun_(&t); - } - -private: - std::function fun_; -}; +void TestFunc(); int main(int argc, char *argv[]) { - auto clz = std::make_shared("Test"); - class Adder adder; - meta::reflection::Method *method = new AdderMethod("Add", clz); - for (int i = 0; i < 10; i++) { - LOGV("", "{}+{}={}", i, i, meta::reflection::any_cast(method->Invoke(&adder, i, i))); - } - - void (Test::*p)(int, double, std::string) = &Test::Show; - LOGV(kTag, "{}", meta::reflection::PrettyName()); // LOGI(kTag, "cwd={}", sled::Path::Current().ToString()); meta::Parser parser; @@ -151,10 +121,31 @@ main(int argc, char *argv[]) LOGI(kTag, "{}\n{}", meta::Registry::Instance()->GetQualifiedName(clz), clz->ToString()); } - Generator generator1("template/class_proxy_include.inja"); + Generator generator1("template/class_proxy_include.inja", "runtime/test.gen.h"); generator1.Generate(); - Generator generator2("template/class_proxy_source.inja"); + Generator generator2("template/class_proxy_source.inja", "runtime/test.gen.cc"); generator2.Generate(); + ::meta::reflection::Registry::RegisterAll(); + TestFunc(); return 0; } + +void +TestFunc() +{ + auto clz = ::meta::reflection::Registry::Instance()->GetClass("test::Test"); + if (clz) { + LOGI(kTag, "class={}", clz->Name()); + ::test::Test test; + auto size_method = clz->GetMethod("size"); + auto size_field = clz->GetField("size_"); + for (int i = 0; i < 10; i++) { + size_field->Set(&test, i); + LOGI(kTag, "size_field={}", size_field->GetAndCast(&test)); + LOGI(kTag, "size_invoke={}", size_method->InvokeAndCast(&test)); + } + } else { + LOGE(kTag, "class not found"); + } +} diff --git a/src/types/field.cc b/src/types/field.cc index ecbdec0..addbc91 100644 --- a/src/types/field.cc +++ b/src/types/field.cc @@ -16,6 +16,18 @@ Field::Field(const Cursor &cursor, const std::vector &namespaces, c } } +bool +Field::IsConst() const +{ + return cursor().GetType().IsConst(); +} + +bool +Field::IsStatic() const +{ + return false; +} + std::string Field::ToString() const { diff --git a/src/types/field.h b/src/types/field.h index f03314b..0948e89 100644 --- a/src/types/field.h +++ b/src/types/field.h @@ -11,6 +11,8 @@ public: Field(const Cursor &cursor, const std::vector &namespaces, const Class &parent); ~Field() override = default; + bool IsConst() const override; + bool IsStatic() const; std::string ToString() const override; std::string TypeName() const override; diff --git a/src/types/method.cc b/src/types/method.cc index e02a5c2..e40f157 100644 --- a/src/types/method.cc +++ b/src/types/method.cc @@ -46,4 +46,10 @@ Method::IsConst() const return clang_CXXMethod_isConst(cursor_.handle()); }; +bool +Method::IsStatic() const +{ + return clang_CXXMethod_isStatic(cursor().handle()); +} + }// namespace meta diff --git a/src/types/method.h b/src/types/method.h index c1a6413..7f5159a 100644 --- a/src/types/method.h +++ b/src/types/method.h @@ -14,6 +14,7 @@ public: std::string TypeName() const override; bool IsConst() const override; + bool IsStatic() const; CursorType return_type() const { return return_type_; } diff --git a/template/class_proxy_include.inja b/template/class_proxy_include.inja index a17a6cf..56d198d 100644 --- a/template/class_proxy_include.inja +++ b/template/class_proxy_include.inja @@ -2,15 +2,22 @@ #ifndef META_GEN_{{class_name}}_PROXY_H #define META_GEN_{{class_name}}_PROXY_H -#include "runtime/reflection.h" +#include "test.h" -namespace meta { -namespace reflection { +// namespace meta { +// namespace reflection { -class {{class_name}}_Class : public ::meta::reflection::Class { +class ::{{class_namespace}}::{{class_name}}::{{class_name}}_Class : public ::meta::reflection::Class { +public: + {{class_name}}_Class(); + static void Register(); +private: + void AddBaseClassProxy(std::shared_ptr<::meta::reflection::Class> base) ; + void AddMethodProxy(std::shared_ptr<::meta::reflection::Method> method) ; + void AddFieldProxy(std::shared_ptr<::meta::reflection::Field> field) ; }; -class {{class_name}}_Field : public ::meta::reflection::Field { +class ::{{class_namespace}}::{{class_name}}::{{class_name}}_Field : public ::meta::reflection::Field { public: {{class_name}}_Field(const std::string& name, std::shared_ptr<::meta::reflection::Class> parent); @@ -19,16 +26,16 @@ protected: void SetImpl(void* instance, const ::meta::reflection::any& value) const override; }; -class {{class_name}}_Method : public ::meta::reflection::Method { +class ::{{class_namespace}}::{{class_name}}::{{class_name}}_Method : public ::meta::reflection::Method { public: {{class_name}}_Method(const std::string& name, std::shared_ptr<::meta::reflection::Class> parent); protected: - ::meta::reflection::any InvokeImpl(void* instance, const std::vector ¶ms) const override; + ::meta::reflection::any InvokeImpl(void* instance, const std::vector<::meta::reflection::any> ¶ms) const override; }; -} // namespace reflection -} // namespace meta +// } // namespace reflection +// } // namespace meta #endif // META_GEN_{{class_name}}_PROXY_H diff --git a/template/class_proxy_source.inja b/template/class_proxy_source.inja index f11999e..6519824 100644 --- a/template/class_proxy_source.inja +++ b/template/class_proxy_source.inja @@ -1,31 +1,69 @@ -#include "{{class_name}}.gen.h" -#include +#include "{{to_lower(class_name)}}.gen.h" +#include + +/** + * Class + **/ +{{class_namespace}}::{{class_name}}::{{class_name}}_Class::{{class_name}}_Class() +: ::meta::reflection::Class("{{class_namespace}}::{{class_name}}", nullptr) +{ +} + +void {{class_namespace}}::{{class_name}}::{{class_name}}_Class::Register() { + auto self = new {{class_namespace}}::{{class_name}}::{{class_name}}_Class(); + auto clz = std::shared_ptr<::meta::reflection::Class>(self); + // self->AddBaseClassProxy(); + +{% for method in class_methods %} + self->AddMethod(std::make_shared<{{class_namespace}}::{{class_name}}::{{class_name}}_Method>("{{method.name}}", clz)); +{% endfor %} + +{% for field in class_fields %} + self->AddField(std::make_shared<{{class_namespace}}::{{class_name}}::{{class_name}}_Field>("{{field.name}}", clz)); +{% endfor %} + + ::meta::reflection::Registry::Instance()->RegisterClass(clz); +} +void {{class_namespace}}::{{class_name}}::{{class_name}}_Class::AddBaseClassProxy(std::shared_ptr<::meta::reflection::Class> base) { + AddBaseClass(base); +} +void {{class_namespace}}::{{class_name}}::{{class_name}}_Class::AddMethodProxy(std::shared_ptr<::meta::reflection::Method> method) { + AddMethod(method); +} +void {{class_namespace}}::{{class_name}}::{{class_name}}_Class::AddFieldProxy(std::shared_ptr<::meta::reflection::Field> field) { + AddField(field); +} -namespace meta { -namespace reflection { /** * Field **/ -{{class_name}}_Field::{{class_name}}_Field( +{{class_namespace}}::{{class_name}}::{{class_name}}_Field::{{class_name}}_Field( const std::string& name, std::shared_ptr<::meta::reflection::Class> parent) : ::meta::reflection::Field(name, parent) {} -::meta::reflection::any GetImpl(void* instance) const { +::meta::reflection::any {{class_namespace}}::{{class_name}}::{{class_name}}_Field::GetImpl(void* instance) const { ::{{class_namespace}}::{{class_name}}* obj = (::{{class_namespace}}::{{class_name}}*)instance; {% for field in class_fields %} - if (strcmp(name().c_str(), "{{field.name}}") == 0) { return obj->{{field.name}}; } + if (strcmp(Name().c_str(), "{{field.name}}") == 0) { + {% if field.is_static %} + return ::{{class_namespace}}::{{class_name}}::{{field.name}}; + {% else %} + return obj->{{field.name}}; + {% endif %} + } {% endfor %} + return ::meta::reflection::any{}; } -void SetImpl(void* instance, const ::meta::reflection::any& value) const { +void {{class_namespace}}::{{class_name}}::{{class_name}}_Field::SetImpl(void* instance, const ::meta::reflection::any& value) const { ::{{class_namespace}}::{{class_name}}* obj = (::{{class_namespace}}::{{class_name}}*)instance; {% for field in class_fields %} {% if not field.is_const %} - if(strcmp(name().c_str(), "{{field.name}}") == 0) { obj->{{field.name}} = value.as<{{field.type}}>();} + if(strcmp(Name().c_str(), "{{field.name}}") == 0) { obj->{{field.name}} = ::meta::reflection::any_cast<{{field.type}}>(value);} {% endif %} {% endfor %} } @@ -35,44 +73,42 @@ void SetImpl(void* instance, const ::meta::reflection::any& value) const { /** * Method **/ -{{class_name}}_Method::{{class_name}}_Method( +{{class_namespace}}::{{class_name}}::{{class_name}}_Method::{{class_name}}_Method( const std::string& name, std::shared_ptr<::meta::reflection::Class> parent) : ::meta::reflection::Method(name, parent) {} -::meta::reflection::any InvokeImpl(void* instance, const std::vector ¶ms) const { +::meta::reflection::any {{class_namespace}}::{{class_name}}::{{class_name}}_Method::InvokeImpl(void* instance, const std::vector<::meta::reflection::any> ¶ms) const { ::{{class_namespace}}::{{class_name}}* obj = (::{{class_namespace}}::{{class_name}}*)instance; {% for method in class_methods %} - {# start if(, else if(, #} - {% if loop.is_first %} - if (strcmp(name.c_str(), "{{method.name}}") == 0) { - {% else %} - } else if (strcmp(name.c_str(), "{{method.name}}") == 0) { - {% endif %} - + if (strcmp(Name().c_str(), "{{method.name}}") == 0) { {% if method.return_type != "void" %} - return obj->{{method.name}}( + return + {% if method.is_static %} + ::{{class_namespace}}::{{class_name}}:: + {% else %} + obj-> + {% endif %}{{method.name}}( {% for param in method.params%} - *({{param.type}}*)params[{{loop.index}}]{% if not loop.is_last %}, {% endif %} + ::meta::reflection::any_cast<{{param.type}}>(params[{{loop.index}}]){% if not loop.is_last %}, {% endif %} {% endfor %} ); {% else %} - obj->{{method.name}}( + {% if method.is_static %} + ::{{class_namespace}}::{{class_name}}:: + {% else %} + obj-> + {%endif%}} + {{method.name}}( {% for param in method.params%} - *({{param.type}}*)params[{{loop.index}}]{% if not loop.last %}, {% endif %} + ::meta::reflection::any_cast<{{param.type}}>(params[{{loop.index}}]){% if not loop.last %}, {% endif %} {% endfor %} ); - return; + return ::meta::reflection::any{}; {% endif %} - - {% if loop.is_last %} } - {% endif %} - {% endfor %} + return ::meta::reflection::any{}; } -} // namespace reflection -} // namespace meta -