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

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend