feat support reflection

This commit is contained in:
tqcq 2024-03-05 00:13:53 +08:00
parent fd8ae6c6bd
commit 6566f11269
17 changed files with 462 additions and 231 deletions

2
3rdparty/sled vendored

@ -1 +1 @@
Subproject commit fcce11249be00ca0c7f8c2e75938de4b3e5f26da Subproject commit 4402688c9c63e9885de1bf99cd718150b036ac7a

View File

@ -18,6 +18,8 @@ add_executable(meta
src/types/field.cc src/types/field.cc
src/types/method.cc src/types/method.cc
src/registry.cc src/registry.cc
runtime/test.gen.cc
runtime/reflection.gen.cc
) )
### add clang ### add clang

View File

@ -1,60 +0,0 @@
#pragma once
#ifndef META_APPLY_H
#define META_APPLY_H
#include <functional>
#include <tuple>
namespace meta {
namespace reflection {
namespace detail {
template<int... Seq>
struct Sequence {};
template<int N, int... Seq>
struct MakeSeq : MakeSeq<N - 1, N - 1, Seq...> {};
template<int... Seq>
struct MakeSeq<0, Seq...> {
using type = Sequence<Seq...>;
};
template<typename ReturnT, typename Func, typename Tuple, int... Seq>
ReturnT
ApplyImpl(const Func &func, const Tuple &tuple, const Sequence<Seq...> &)
{
return std::bind(func, std::get<Seq>(tuple)...)();
}
struct VoidTag {};
}// namespace detail
template<typename ReturnT,
typename Func,
typename Tuple,
typename std::enable_if<!std::is_void<ReturnT>::value, ReturnT>::type * = nullptr>
ReturnT
apply(const Func &func, const Tuple &tuple)
{
return detail::ApplyImpl<ReturnT>(
func,
tuple,
typename detail::MakeSeq<std::tuple_size<Tuple>::value>::type());
}
template<typename ReturnT = void,
typename Func,
typename Tuple,
typename std::enable_if<std::is_void<ReturnT>::value, detail::VoidTag>::type * = nullptr>
ReturnT
apply(const Func &func, const Tuple &tuple)
{
return detail::ApplyImpl<ReturnT>(
func,
tuple,
typename detail::MakeSeq<std::tuple_size<Tuple>::value>::type());
}
}// namespace reflection
}// namespace meta
#endif// META_APPLY_H

View File

@ -0,0 +1,5 @@
#include "test.gen.h"
void ::meta::reflection::Registry::RegisterAll() { ::test::Test::Test_Class::Register(); }
void ::meta::reflection::Registry::UnregisterAll() {}

View File

@ -2,7 +2,6 @@
#ifndef META_RUNTIME_REFLECTION_H #ifndef META_RUNTIME_REFLECTION_H
#define META_RUNTIME_REFLECTION_H #define META_RUNTIME_REFLECTION_H
#include "any.h" #include "any.h"
#include "apply.h"
#include <cstdlib> #include <cstdlib>
#include <cxxabi.h> #include <cxxabi.h>
#include <sled/log/log.h> #include <sled/log/log.h>
@ -42,7 +41,7 @@ RemoveTypeSpace(const std::string &str, const std::string &chars = "[]()<>*&:")
} }
template<typename T, typename U = typename std::decay<T>::type> template<typename T, typename U = typename std::decay<T>::type>
std::string inline std::string
PrettyNameImpl() PrettyNameImpl()
{ {
const std::string name = typeid(U).name(); const std::string name = typeid(U).name();
@ -71,13 +70,20 @@ PrettyName()
#define META(...) #define META(...)
#define CLASS(class_name, ...) class class_name #define CLASS(class_name, ...) class class_name
#define STRUCT(struct_name, ...) struct struct_name #define STRUCT(struct_name, ...) struct struct_name
#endif// __REFLECTION_PARSER_ #endif// __REFLECTION_PARSER_ \
#define META_REFLECTION_BODY(class_name) \ #define META_REFLECTION_BODY(class_name) \
friend class meta::reflection::##class_name##_Method; \ class class_name##_Class; \
friend class meta::reflection::##class_name##_Field; \ class class_name##_Constructor; \
friend class meta::reflection::##class_name##_Constructor; \ class class_name##_Method; \
friend class meta::reflection::##class_name##_Serializer; 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 Constructor;
class Method; class Method;
@ -113,7 +119,7 @@ public:
typename... Params> typename... Params>
inline ReturnT InvokeAndCast(void *instance, Params &&...params) const inline ReturnT InvokeAndCast(void *instance, Params &&...params) const
{ {
return ::meta::reflection::any_cast<ReturnT>(InvokeImpl(instance, {&params...})); return ::meta::reflection::any_cast<ReturnT>(InvokeImpl(instance, {params...}));
} }
template<typename ReturnT, template<typename ReturnT,
@ -121,18 +127,18 @@ public:
typename... Params> typename... Params>
inline void InvokeAndCast(void *instance, Params &&...params) const inline void InvokeAndCast(void *instance, Params &&...params) const
{ {
::meta::reflection::any_cast<ReturnT>(InvokeImpl(instance, {&params...})); ::meta::reflection::any_cast<ReturnT>(InvokeImpl(instance, {params...}));
} }
template<typename... Params> template<typename... Params>
inline ::meta::reflection::any Invoke(void *instance, Params &&...params) const inline ::meta::reflection::any Invoke(void *instance, Params &&...params) const
{ {
return InvokeImpl(instance, {&params...}); return InvokeImpl(instance, {params...});
} }
protected: protected:
virtual ::meta::reflection::any InvokeImpl(void *instance, virtual ::meta::reflection::any
const std::vector<void *> &params) const InvokeImpl(void *instance, const std::vector<::meta::reflection::any> &params) const
= 0; = 0;
private: private:
@ -167,23 +173,106 @@ public:
Class(const std::string &name, std::shared_ptr<Class> base_class = nullptr) Class(const std::string &name, std::shared_ptr<Class> base_class = nullptr)
: BaseType(name, base_class) : BaseType(name, base_class)
{} {}
inline std::vector<std::shared_ptr<Class>> GetBaseClasses() const { return base_classes_; }
inline std::shared_ptr<Class> 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<std::shared_ptr<Method>> GetMethods() const { return methods_; }
inline std::shared_ptr<Method> 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<std::shared_ptr<Field>> GetFields() const { return fields_; }
inline std::shared_ptr<Field> 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<Class> 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> 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> field)
{
fields_.push_back(field);
field_by_name_[field->Name()] = field;
}
private:
std::unordered_map<std::string, std::shared_ptr<Class>> base_class_by_name_;
std::unordered_map<std::string, std::shared_ptr<Method>> method_by_name_;
std::unordered_map<std::string, std::shared_ptr<Field>> field_by_name_;
std::vector<std::shared_ptr<Class>> base_classes_;
std::vector<std::shared_ptr<Method>> methods_;
std::vector<std::shared_ptr<Field>> fields_;
}; };
#define REFLECTION_BODY() \ class Registry {
friend class meta::Serializer; \
friend class meta::Class; \
friend class meta::Method; \
friend class meta::Field; \
friend class meta::Constructor;
class Reflectioin {
public: public:
static Reflectioin *Instance(); static Registry *Instance()
~Reflectioin(); {
std::shared_ptr<Class> GetClass(); static Registry instance;
// std::shared_ptr<Constructor> GetConstructor(std::shared_ptr<Class> clz); return &instance;
std::shared_ptr<Method> GetMethod(std::shared_ptr<Class> clz); }
std::shared_ptr<Field> GetField(std::shared_ptr<Class> clz);
~Registry() {}
static void RegisterAll();
static void UnregisterAll();
static std::shared_ptr<Class> GetClass(const std::string &name)
{
return Instance()->GetClassInner(name);
}
static void RegisterClass(std::shared_ptr<Class> clz) { Instance()->RegisterClassInner(clz); }
static std::vector<std::shared_ptr<Class>> GetClasses() { return Instance()->classes(); }
private:
std::shared_ptr<Class> 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<Class> 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<std::shared_ptr<Class>> classes() const { return classes_; }
std::unordered_map<std::string, std::shared_ptr<Class>> class_by_name_;
std::vector<std::shared_ptr<Class>> classes_;
}; };
}// namespace reflection }// namespace reflection

90
runtime/test.gen.cc Normal file
View File

@ -0,0 +1,90 @@
#include "test.gen.h"
#include <memory>
/**
* 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<test::Test::Test_Method>("size", clz));
self->AddMethod(std::make_shared<test::Test::Test_Method>("length", clz));
self->AddField(std::make_shared<test::Test::Test_Field>("length_", clz));
self->AddField(std::make_shared<test::Test::Test_Field>("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<int>(value);}
if(strcmp(Name().c_str(), "size_") == 0) { obj->size_ = ::meta::reflection::any_cast<int>(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> &params) 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{};
}

41
runtime/test.gen.h Normal file
View File

@ -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> &params) const override;
};
// } // namespace reflection
// } // namespace meta
#endif // META_GEN_Test_PROXY_H

View File

@ -3,38 +3,25 @@
#define META_RUNTIME_TEST_H #define META_RUNTIME_TEST_H
#include "reflection.h" #include "reflection.h"
#include <vector>
namespace test { namespace test {
class TypeDef {};
CLASS(Test) CLASS(Test)
{ {
META_REFLECTION_BODY(Test);
public: public:
META("Constructor") Test() {}
Test() : b_(0), a_(0) {}
Test(int a) : b_(0), a_(a) {} const size_t size() const { return size_; }
const size_t length() const { return length_; }
META("Test")
int GetA() const { return a_; }
int kk(int, void *);
TypeDef GetTypeDef() const { return type_def_; }
private: private:
struct Void {}; META("1")
int length_;
STRUCT(VoidMeta, "VoidMeta") META("2")
{ int size_;
META("Enable")
int a;
};
const int b_;
int a_;
META("TypeDef")
TypeDef type_def_;
}; };
}// namespace test }// namespace test

View File

@ -59,6 +59,7 @@ Parser::Parse(const std::string &file_name, std::vector<const char *> extra_args
// ignore error for reflection.h // ignore error for reflection.h
if (sled::EndsWith(filename, "reflection.h")) { continue; } if (sled::EndsWith(filename, "reflection.h")) { continue; }
if (sled::EndsWith(filename, "any.h")) { continue; }
LOGE("parser", "diagnostic: {}", msg); LOGE("parser", "diagnostic: {}", msg);
} }

View File

@ -39,19 +39,38 @@ BaseGenerator::GenClassRenderData(Class *clz, inja::json &class_def)
class_def["properties"] = inja::json::array(); class_def["properties"] = inja::json::array();
for (auto &prop : clz->properties()) { class_def["properties"].push_back(prop); } 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 methods = inja::json::array();
inja::json fields = inja::json::array(); inja::json fields = inja::json::array();
GenClassConstructorRenderData(clz, constructors);
GenClassMethodRenderData(clz, methods); GenClassMethodRenderData(clz, methods);
GenClassFieldRenderData(clz, fields); GenClassFieldRenderData(clz, fields);
class_def["class_constructors"] = constructors;
class_def["class_methods"] = methods; class_def["class_methods"] = methods;
class_def["class_fields"] = fields; class_def["class_fields"] = fields;
} }
void void
BaseGenerator::GenClassConstructorRenderData(Class *clz, inja::json &constructor_defs) 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 &param : constructor->arguments()) {
inja::json param_def;
param_def["name"] = "";
param_def["type"] = param.GetDisplayName();
params.push_back(param_def);
}
}
}
void void
BaseGenerator::GenClassFieldRenderData(Class *clz, inja::json &field_defs) BaseGenerator::GenClassFieldRenderData(Class *clz, inja::json &field_defs)
@ -60,6 +79,7 @@ BaseGenerator::GenClassFieldRenderData(Class *clz, inja::json &field_defs)
inja::json field_def; inja::json field_def;
field_def["name"] = field->Name(); field_def["name"] = field->Name();
field_def["is_const"] = field->IsConst(); field_def["is_const"] = field->IsConst();
field_def["is_static"] = field->IsStatic();
field_def["properties"] = inja::json::array(); field_def["properties"] = inja::json::array();
for (auto &prop : field->properties()) { field_def["properties"].push_back(prop); } for (auto &prop : field->properties()) { field_def["properties"].push_back(prop); }
field_def["type"] = field->cursor().GetType().GetDisplayName(); field_def["type"] = field->cursor().GetType().GetDisplayName();
@ -73,9 +93,10 @@ BaseGenerator::GenClassMethodRenderData(Class *clz, inja::json &method_defs)
for (auto &method : clz->methods()) { for (auto &method : clz->methods()) {
inja::json method_def; inja::json method_def;
method_def["name"] = method->Name(); method_def["name"] = method->Name();
method_def["is_const"] = method->IsConst();
method_def["is_static"] = method->IsStatic();
method_def["properties"] = inja::json::array(); method_def["properties"] = inja::json::array();
for (auto &prop : method->properties()) { method_def["properties"].push_back(prop); } 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(); method_def["return_type"] = method->return_type().GetDisplayName();
inja::json params = inja::json::array(); inja::json params = inja::json::array();
for (auto &param : method->arguments()) { for (auto &param : method->arguments()) {

View File

@ -1,6 +1,7 @@
#include "generators/base_generator.h" #include "generators/base_generator.h"
#include "reflection.h" #include "reflection.h"
#include "registry.h" #include "registry.h"
#include "test.gen.h"
#include "types/class.h" #include "types/class.h"
#include "clang/parser.h" #include "clang/parser.h"
#include <fstream> #include <fstream>
@ -15,12 +16,13 @@ const char *kTag = "main";
class Generator : public meta::BaseGenerator { class Generator : public meta::BaseGenerator {
public: 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::fstream in(template_path, std::ios::in);
std::stringstream ss; std::stringstream ss;
ss << in.rdbuf(); ss << in.rdbuf();
template_ = ss.str(); template_ = ss.str();
output_path_ = output_path;
} }
~Generator() override = default; ~Generator() override = default;
@ -33,9 +35,51 @@ public:
inja::Environment env; inja::Environment env;
env.set_trim_blocks(true); env.set_trim_blocks(true);
env.set_lstrip_blocks(true); env.set_lstrip_blocks(true);
env.add_callback("to_upper", 1, [](inja::Arguments &args) {
return sled::ToUpper(args.at(0)->get<std::string>());
});
env.add_callback("to_lower", 1, [](inja::Arguments &args) {
return sled::ToLower(args.at(0)->get<std::string>());
});
// 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>();
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>();
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 { try {
LOGV(kTag, "data={}", class_def.dump()); 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) { } catch (const std::exception &e) {
LOGE(kTag, "error: {}", e.what()); LOGE(kTag, "error: {}", e.what());
} }
@ -44,88 +88,14 @@ public:
private: private:
std::string template_; std::string template_;
std::string output_path_;
}; };
// template<typename ClassT, typename ReturnT = void, typename... Args> void TestFunc();
// std::function<void(sled::any)>
// MemberFunctionWrapper(void (ClassT::*func)(Args...))
// {
// return [=](sled::any obj_args) {
// using tuple = ::std::tuple<ClassT *, Args...>;
// // ::std::tuple<ClassT *, Args...> *pTuple = ::sled::any_cast<tuple *>(obj_args);
// auto tuple_ptr = ::sled::any_cast<tuple *>(obj_args);
// sled::apply(func, *tuple_ptr);
// };
// }
template<typename ClassT, typename ReturnT, typename... Args>
std::function<ReturnT(sled::any)>
MemberFunctionWrapper(ReturnT (ClassT::*func)(Args...))
{
return [=](sled::any obj_args) {
using tuple = ::std::tuple<ClassT *, Args...>;
// ::std::tuple<ClassT *, Args...> *pTuple = ::sled::any_cast<tuple *>(obj_args);
auto tuple_ptr = ::sled::any_cast<tuple *>(obj_args);
return sled::apply<ReturnT>(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<meta::reflection::Class> parent)
: meta::reflection::Method(name, parent)
{
fun_ = MemberFunctionWrapper<Adder, int, int, int>(&Adder::Add);
}
int Add(int a, int b) { return a + b; }
protected:
meta::reflection::any InvokeImpl(void *instance,
const std::vector<void *> &params) const override
{
Adder *adder = reinterpret_cast<Adder *>(instance);
using tuple = std::tuple<int, int>;
auto t = std::make_tuple(adder,
*reinterpret_cast<int *>(params[0]),
*reinterpret_cast<int *>(params[1]));
return fun_(&t);
}
private:
std::function<int(sled::any)> fun_;
};
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
auto clz = std::make_shared<meta::reflection::Class>("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<int>(method->Invoke(&adder, i, i)));
}
void (Test::*p)(int, double, std::string) = &Test::Show;
LOGV(kTag, "{}", meta::reflection::PrettyName<meta::Registry>()); LOGV(kTag, "{}", meta::reflection::PrettyName<meta::Registry>());
// LOGI(kTag, "cwd={}", sled::Path::Current().ToString()); // LOGI(kTag, "cwd={}", sled::Path::Current().ToString());
meta::Parser parser; meta::Parser parser;
@ -151,10 +121,31 @@ main(int argc, char *argv[])
LOGI(kTag, "{}\n{}", meta::Registry::Instance()->GetQualifiedName(clz), clz->ToString()); 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(); generator1.Generate();
Generator generator2("template/class_proxy_source.inja"); Generator generator2("template/class_proxy_source.inja", "runtime/test.gen.cc");
generator2.Generate(); generator2.Generate();
::meta::reflection::Registry::RegisterAll();
TestFunc();
return 0; 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<int>(&test));
LOGI(kTag, "size_invoke={}", size_method->InvokeAndCast<size_t>(&test));
}
} else {
LOGE(kTag, "class not found");
}
}

View File

@ -16,6 +16,18 @@ Field::Field(const Cursor &cursor, const std::vector<std::string> &namespaces, c
} }
} }
bool
Field::IsConst() const
{
return cursor().GetType().IsConst();
}
bool
Field::IsStatic() const
{
return false;
}
std::string std::string
Field::ToString() const Field::ToString() const
{ {

View File

@ -11,6 +11,8 @@ public:
Field(const Cursor &cursor, const std::vector<std::string> &namespaces, const Class &parent); Field(const Cursor &cursor, const std::vector<std::string> &namespaces, const Class &parent);
~Field() override = default; ~Field() override = default;
bool IsConst() const override;
bool IsStatic() const;
std::string ToString() const override; std::string ToString() const override;
std::string TypeName() const override; std::string TypeName() const override;

View File

@ -46,4 +46,10 @@ Method::IsConst() const
return clang_CXXMethod_isConst(cursor_.handle()); return clang_CXXMethod_isConst(cursor_.handle());
}; };
bool
Method::IsStatic() const
{
return clang_CXXMethod_isStatic(cursor().handle());
}
}// namespace meta }// namespace meta

View File

@ -14,6 +14,7 @@ public:
std::string TypeName() const override; std::string TypeName() const override;
bool IsConst() const override; bool IsConst() const override;
bool IsStatic() const;
CursorType return_type() const { return return_type_; } CursorType return_type() const { return return_type_; }

View File

@ -2,15 +2,22 @@
#ifndef META_GEN_{{class_name}}_PROXY_H #ifndef META_GEN_{{class_name}}_PROXY_H
#define META_GEN_{{class_name}}_PROXY_H #define META_GEN_{{class_name}}_PROXY_H
#include "runtime/reflection.h" #include "test.h"
namespace meta { // namespace meta {
namespace reflection { // 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: public:
{{class_name}}_Field(const std::string& name, std::shared_ptr<::meta::reflection::Class> parent); {{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; 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: public:
{{class_name}}_Method(const std::string& name, std::shared_ptr<::meta::reflection::Class> parent); {{class_name}}_Method(const std::string& name, std::shared_ptr<::meta::reflection::Class> parent);
protected: protected:
::meta::reflection::any InvokeImpl(void* instance, const std::vector<void *> &params) const override; ::meta::reflection::any InvokeImpl(void* instance, const std::vector<::meta::reflection::any> &params) const override;
}; };
} // namespace reflection // } // namespace reflection
} // namespace meta // } // namespace meta
#endif // META_GEN_{{class_name}}_PROXY_H #endif // META_GEN_{{class_name}}_PROXY_H

View File

@ -1,31 +1,69 @@
#include "{{class_name}}.gen.h" #include "{{to_lower(class_name)}}.gen.h"
#include <string.h> #include <memory>
/**
* 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 * Field
**/ **/
{{class_name}}_Field::{{class_name}}_Field( {{class_namespace}}::{{class_name}}::{{class_name}}_Field::{{class_name}}_Field(
const std::string& name, const std::string& name,
std::shared_ptr<::meta::reflection::Class> parent) std::shared_ptr<::meta::reflection::Class> parent)
: ::meta::reflection::Field(name, 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; ::{{class_namespace}}::{{class_name}}* obj = (::{{class_namespace}}::{{class_name}}*)instance;
{% for field in class_fields %} {% 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 %} {% 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; ::{{class_namespace}}::{{class_name}}* obj = (::{{class_namespace}}::{{class_name}}*)instance;
{% for field in class_fields %} {% for field in class_fields %}
{% if not field.is_const %} {% 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 %} {% endif %}
{% endfor %} {% endfor %}
} }
@ -35,44 +73,42 @@ void SetImpl(void* instance, const ::meta::reflection::any& value) const {
/** /**
* Method * Method
**/ **/
{{class_name}}_Method::{{class_name}}_Method( {{class_namespace}}::{{class_name}}::{{class_name}}_Method::{{class_name}}_Method(
const std::string& name, const std::string& name,
std::shared_ptr<::meta::reflection::Class> parent) std::shared_ptr<::meta::reflection::Class> parent)
: ::meta::reflection::Method(name, parent) {} : ::meta::reflection::Method(name, parent) {}
::meta::reflection::any InvokeImpl(void* instance, const std::vector<void *> &params) const { ::meta::reflection::any {{class_namespace}}::{{class_name}}::{{class_name}}_Method::InvokeImpl(void* instance, const std::vector<::meta::reflection::any> &params) const {
::{{class_namespace}}::{{class_name}}* obj = (::{{class_namespace}}::{{class_name}}*)instance; ::{{class_namespace}}::{{class_name}}* obj = (::{{class_namespace}}::{{class_name}}*)instance;
{% for method in class_methods %} {% for method in class_methods %}
{# start if(, else if(, #} if (strcmp(Name().c_str(), "{{method.name}}") == 0) {
{% if loop.is_first %}
if (strcmp(name.c_str(), "{{method.name}}") == 0) {
{% else %}
} else if (strcmp(name.c_str(), "{{method.name}}") == 0) {
{% endif %}
{% if method.return_type != "void" %} {% 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%} {% 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 %} {% endfor %}
); );
{% else %} {% else %}
obj->{{method.name}}( {% if method.is_static %}
::{{class_namespace}}::{{class_name}}::
{% else %}
obj->
{%endif%}}
{{method.name}}(
{% for param in method.params%} {% 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 %} {% endfor %}
); );
return; return ::meta::reflection::any{};
{% endif %} {% endif %}
{% if loop.is_last %}
} }
{% endif %}
{% endfor %} {% endfor %}
return ::meta::reflection::any{};
} }
} // namespace reflection
} // namespace meta