building a c reflection system
play

Building a C++ Reflection System Using LLVM and Clang 1 Meeting - PowerPoint PPT Presentation

Building a C++ Reflection System Using LLVM and Clang 1 Meeting C++ 2018 / @ArvidGerstmann Storytime 2 Meeting C++ 2018 / @ArvidGerstmann Wouldn't it be great ... 3 Meeting C++ 2018 / @ArvidGerstmann struct User { uint64_t id;


  1. Building a C++ Reflection System Using LLVM and Clang 1 — Meeting C++ 2018 / @ArvidGerstmann

  2. Storytime 2 — Meeting C++ 2018 / @ArvidGerstmann

  3. Wouldn't it be great ... 3 — Meeting C++ 2018 / @ArvidGerstmann

  4. struct User { uint64_t id; strin g name; vector<strin g > pets; }; User user; user.id = 42; user.name = "John"; user.pets.push_back("Buddy"); user.pets.push_back("Cooper"); strin g json = json::Strin g ify(&user); 4 — Meeting C++ 2018 / @ArvidGerstmann

  5. { "id": 42, "name": "John", "pets": ["Buddy", "Cooper"] } 5 — Meeting C++ 2018 / @ArvidGerstmann

  6. How do we do this? 6 — Meeting C++ 2018 / @ArvidGerstmann

  7. strin g json::Strin g ify(User const * user) { JsonSerializer serializer; serializer.SerializeInt64("id", user->id); serializer.SerializeStrin g ("name", user->name); serializer.Be g inArray("pets"); for (auto const &pet : user->pets) serializer.ArrayAddStrin g (pet); serializer.EndArray(); return serializer.ToStrin g (); } 7 — Meeting C++ 2018 / @ArvidGerstmann

  8. class User { public ulon g id; public strin g name; public List<strin g > pets = new List<strin g >(); } User user = new User(); user.id = 42; user.name = "John"; user.pets.Add("Buddy"); user.pets.Add("Cooper"); strin g json = JsonConvert.SerializeObject(user); 8 — Meeting C++ 2018 / @ArvidGerstmann

  9. Reflection 9 — Meeting C++ 2018 / @ArvidGerstmann

  10. Type t = user.GetType(); 10 — Meeting C++ 2018 / @ArvidGerstmann

  11. • GetField(String, BindingFlags) • GetFields(BindingFlags) • GetInterface(String, Boolean) • GetInterfaces() • GetMethodImpl(String, BindingFlags, Binder, CallingConventions, Type[], ParameterModifier[]) • GetMethods(BindingFlags) • GetNestedType(String, BindingFlags) • GetNestedTypes(BindingFlags) • GetProperties(BindingFlags) • GetPropertyImpl(String, BindingFlags, Binder, Type, Type[], ParameterModifier[]) • HasElementTypeImpl() • InvokeMember(String, BindingFlags, Binder, Object, Object[], ParameterModifier[], CultureInfo, String[]) • IsArrayImpl() • IsByRefImpl() • IsCOMObjectImpl() • IsPointerImpl() • IsPrimitiveImpl() 11 — Meeting C++ 2018 / @ArvidGerstmann

  12. • GetField(String, BindingFlags) • GetFields(BindingFlags) • GetInterface(String, Boolean) • GetInterfaces() • GetMethodImpl(String, BindingFlags, Binder, CallingConventions, Type[], ParameterModifier[]) • GetMethods(BindingFlags) • GetNestedType(String, BindingFlags) • GetNestedTypes(BindingFlags) • GetProperties(BindingFlags) • GetPropertyImpl(String, BindingFlags, Binder, Type, Type[], ParameterModifier[]) • HasElementTypeImpl() • InvokeMember(String, BindingFlags, Binder, Object, Object[], ParameterModifier[], CultureInfo, String[]) • IsArrayImpl() • IsByRefImpl() • IsCOMObjectImpl() • IsPointerImpl() • IsPrimitiveImpl() 12 — Meeting C++ 2018 / @ArvidGerstmann

  13. Type t = user.GetType(); FieldInfo[] fields = t.GetFields(...); foreach (var field in fields) { Console.WriteLine("Name: { 0 }", field.Name); Console.WriteLine("Type: { 0 }", field.FieldType); Console.WriteLine(); } 13 — Meeting C++ 2018 / @ArvidGerstmann

  14. Name: id Type: System.UInt64 Name: name Type: System.Strin g Name: pets Type: System.Collections.Generic.List`1[System.Strin g ] 14 — Meeting C++ 2018 / @ArvidGerstmann

  15. Back to C++ 15 — Meeting C++ 2018 / @ArvidGerstmann

  16. Class const * c = GetClass<User>(); for (auto &field : c->Fields()) { printf("Name: %s\n", field.Name()); printf("Type: %s\n", field.Type().Name()); printf("\n"); } 16 — Meeting C++ 2018 / @ArvidGerstmann

  17. Blueprint 17 — Meeting C++ 2018 / @ArvidGerstmann

  18. struct Type { char const * name; size_t size; }; 18 — Meeting C++ 2018 / @ArvidGerstmann

  19. struct Class : public Type { Field fields[N]; Function functions[N]; }; 19 — Meeting C++ 2018 / @ArvidGerstmann

  20. struct Field { Type * type; char const * name; size_t offset; }; struct Function { Field returnValue; Field parameters[N]; char const * name; }; 20 — Meeting C++ 2018 / @ArvidGerstmann

  21. struct Type { char const * name; size_t size; }; struct Field { Type * type; char const * name; size_t offset; }; struct Function { Field returnValue; Field parameters[N]; char const * name; }; struct Class : public Type { Field fields[N]; Function functions[N]; }; 21 — Meeting C++ 2018 / @ArvidGerstmann

  22. Data? 22 — Meeting C++ 2018 / @ArvidGerstmann

  23. struct User { uint64_t id; strin g name; vector<strin g > pets; }; 23 — Meeting C++ 2018 / @ArvidGerstmann

  24. Class const * GetClass<User>() { static Class clazz; clazz.fields[ 0 ].type = GetType<uint64_t>(); clazz.fields[ 0 ].name = "id"; clazz.fields[ 0 ].offset = offsetof(User, id); clazz.fields[1].type = GetType<strin g >(); clazz.fields[1].name = "name"; clazz.fields[1].offset = offsetof(User, name); clazz.fields[2].type = GetType<vector<user>>(); clazz.fields[2].name = "pets"; clazz.fields[2].offset = offsetof(User, pets); return &clazz; } 24 — Meeting C++ 2018 / @ArvidGerstmann

  25. Undefined symbols for architecture x86_64: "Type const * GetType<std::__1::basic_strin g <char, std::__1::char_traits<char>, std::__1::allocator<char> > >()", referenced from: _main in Untitled 7- 0 fb8bc.o "Type const * GetType<std::__1::vector<std::__1::basic_strin g <char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_strin g <char, std::__1::char_traits<char>, std::__1::allocator<char> > > > >()", referenced from: _main in Untitled 7- 0 fb8bc.o "Type const * GetType<unsi g ned lon g lon g >()", referenced from: _main in Untitled 7- 0 fb8bc.o ld: symbol(s) not found for architecture x86_64 25 — Meeting C++ 2018 / @ArvidGerstmann

  26. "Primitive" Types 26 — Meeting C++ 2018 / @ArvidGerstmann

  27. template<> Type const * GetType<int>() { static Type t{"int", sizeof(int)}; return &t; } 27 — Meeting C++ 2018 / @ArvidGerstmann

  28. template<class T> Type const * GetType() { return detail::GetTypeImpl(TypeTa g <T>{}); } template<class T> Type const * GetTypeImpl(TypeTa g <vector<T>>) { / * ... * / } 28 — Meeting C++ 2018 / @ArvidGerstmann

  29. Class const * GetClassImpl(ClassTa g <User>) { static Class clazz; clazz.fields[ 0 ].type = GetType<uint64_t>(); clazz.fields[ 0 ].name = "id"; clazz.fields[ 0 ].offset = offsetof(User, id); clazz.fields[1].type = GetType<strin g >(); clazz.fields[1].name = "name"; clazz.fields[1].offset = offsetof(User, name); clazz.fields[2].type = GetType<vector<user>>(); clazz.fields[2].name = "pets"; clazz.fields[2].offset = offsetof(User, pets); return &clazz; } 29 — Meeting C++ 2018 / @ArvidGerstmann

  30. Class const * c = GetClass<User>(); for (auto &field : c->Fields()) { printf("Name: %s\n", field.Name()); printf("Type: %s\n", field.Type().Name()); printf("\n"); } 30 — Meeting C++ 2018 / @ArvidGerstmann

  31. Name: id Type: uint64_t Name: name Type: std::strin g Name: pets Type: std::vector<std::strin g > 31 — Meeting C++ 2018 / @ArvidGerstmann

  32. LLVM 32 — Meeting C++ 2018 / @ArvidGerstmann

  33. Clang 33 — Meeting C++ 2018 / @ArvidGerstmann

  34. LibTooling 34 — Meeting C++ 2018 / @ArvidGerstmann

  35. How? 35 — Meeting C++ 2018 / @ArvidGerstmann

  36. Hello, AST 36 — Meeting C++ 2018 / @ArvidGerstmann

  37. struct Foo { volatile int bar; float baz; }; 37 — Meeting C++ 2018 / @ArvidGerstmann

  38. % clan g -Xclan g -ast-dump -fsyntax-only foo.h TranslationUnitDecl 0 x7ff8b 00 264d 0 <<invalid sloc>> <invalid sloc> `-RecordDecl 0 x7f9f2a82712 0 <foo.h:1:1, line:4:1> line:1:8 struct Foo definition |-FieldDecl 0 x7f9f2a8774 00 <line:2:5, col:18> col:18 bar 'volatile int' `-FieldDecl 0 x7f9f2a87746 0 <line:3:5, col:11> col:11 baz 'float' 38 — Meeting C++ 2018 / @ArvidGerstmann

  39. libTooling AST Visitor 39 — Meeting C++ 2018 / @ArvidGerstmann

  40. struct DumpASTAction : public ASTFrontendAction { std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &ci, Strin g Ref inFile) override { return clan g ::CreateASTDumper( nullptr,/ * dump to stdout * / "", / * no filter * / true, / * dump decls * / true, / * deserialize * / false / * don't dump lookups * / ); } }; static llvm::cl::OptionCate g ory g ToolCate g ory("metareflect options"); int main(int ar g c, char ** ar g v) { CommonOptionsParser optionsParser(ar g c, ar g v, g ToolCate g ory); Clan g Tool tool(optionsParser. g etCompilations(), optionsParser. g etSourcePathList()); return tool.run(newFrontendActionFactory<DumpASTAction>(). g et()); } 40 — Meeting C++ 2018 / @ArvidGerstmann

Recommend


More recommend