How would you implement basic reflection in C ++?

I'm thinking of adding some reflection capabilities to some C ++ classes (so I would not have to use RTTI): getting method names, declared fields, class name ... this kind of stuff.

I thought about analyzing existing source files, getting a list of declared fields and methods, and rewriting each source file, adding this information to each class.

What do you think of this approach? I would like to do everything from scratch, as I think this is a great opportunity to learn. Do you suggest other ways to do this?

// OFFTOPIC: this is how Qt does it?

+7
c ++ reflection parsing
source share
9 answers

Check out Boost.Mirror . This is not yet accepted in Boost, so you need to download it from Boost Vault.

The library is still under development, and the documents are not enough, but by studying the above examples , you can achieve what you want.

EDIT: if you really want to parse your own C ++ code, then maybe you should think about clang

+3
source share

I would unlock gcc.

+3
source share

Yes, thatโ€™s exactly how Qt does it, except that it doesnโ€™t add information to the class itself, it creates a new class called a metaclass that contains static data about this class. This is better for obvious reasons.

No approach in pure C ++ will provide fully automatic reflection - the language does not allow this. There are many attempts, including Boost.Mirror and Boost.Reflection , but all of them require adding templates to your source.

+2
source share

If you do not want to modify the C ++ compiler or are not dependent on vendor extensions, you will need a bunch of CPP macros that create data structures.

+1
source share

You can find gccxml . It (for example) converts this to this , which means you just need to parse the XML instead of C ++.

There's an interesting SP & E article that describes the use of gccxml in conjunction with a modified linker to "provide the Java-reflected function of C ++ applications in a clean and non-intrusive way."

+1
source share

Modify the compiler to create a static GetClass method, returning a pointer to a class object that describes the class for each specific class.

Modify the compiler / linker to pull out the necessary metadata and fill it in special sections / symbols of the resulting executable image - just as debugging symbols are added.

GetClass will use (read / load / cache?) The above metadata.

And yes. This is a lot of work. (And the nice side effect is that you almost completely eliminate the destruction of header files - since this information can now be pulled directly from the image)

+1
source share

C ++ does not support reflection. Boost and RTTI efforts are quite limited and half baked. I would not recommend them.

You mentioned that you can start with scatch. Well, you can write C ++ vocabulary using lex / yacc, or ANTLR . A lot of work, but you will learn a lot.

Writing a parser is a formidable task for you; there are other options for getting class metadata. Microsoft has a DIA SDK that provides character information. Doxygen can generate XML files that can be parsed to get field names, class method names. I had some success parsing doxygen XML files.

If you work only with the Microsoft platform, a viable solution is to use a type library (TLB). To do this, you need to convert the class to an interface in MS IDL. MIDL compiles the IDL into .tlb, and your application can load the .tlb file at runtime. Your application can get almost all class information through the ITypeInfo interface, properties, and methods.

+1
source share

Follow the tenth law of Greenspun, and you're good to go: just implement the special, informally indicated, error-loaded, slow implementation of half of Common Lisp. Choose the half that supports reflection implementation. :)

Or, here's the idea:

Include map files (and possibly assembly) in your assembly. Implement an application that generates code to create a dynamic library. You should be able to get all the static information (method names, parameters, types, etc.) About classes from the source or one of the assembly artifacts. Using a map or assembly, you can find addresses of functions, offsets of pointers to virtual functions, addresses of global variables, offsets of variables, stack information and register distributed variables, etc. Etc. From this information, create a library containing calls to get all this information by passing type names, pointers, function names, etc.

Now, in C ++, write a library containing functions and macros that will allow you to put a unique identifier that will be compiled into code to identify the start of the function, all reflection calls, EIP offsets on reflection calls, etc. Use the built-in assembly macros in appropriate places where, if necessary, the NOP needs to leave a few instructions, usually immediately after the ID. In addition, provide bridge library functions that allow reflection functionality or process what it can embed (for example, get the address of a function) and make calls to a dynamic library built at the post-build stage.

Finally, write a post-post build reflection linker. I suggest "kniltsoPostlink", but it is up to you. At this step, find your unique identifiers (I mentioned to make it easier for you, maybe you should make ID identifiers so that you can look for them in binary format?), And wherever the identifier marks a function reflection call, or class definition, etc. .d., place enough data there (in a format that you can easily determine exactly in time when you write the reflector library), and then in the identifier before calling the reflector library, rewrite the call so that it extracts the parameter it needs s of these data bits or just puts data bits there, if applicable, I canโ€™t know in advance, but as you write it, these little details will just pop up on you.

In any case, I know that I did not get a lot of code, and in fact I intend to start a project on this subject when I have enough free time. I mean that each small part should be very simple, since you are doing it gradually, each small part should become clear if you follow the instructions outlined here. It is possible that some of them will actually be even simpler than I described here, because it was the worst case scenario. You can even leave without even rewriting the code for the reflector; simply placing data at appropriate points may allow the library to draw these bits as needed without additional information.

I am very glad you asked; I'm very busy right now, but if you get the night for free, I think it will be a good start in the first version, and I will be glad if I can.

;)

+1
source share

Perhaps you can use the typeinfo library with which you can now become a class of objects at runtime. Example:

#include<iostream> #include<typeinfo> class A{}; int main() { A a; std::cout<<typeid(a).name(); } 

You can see more: http://www.cplusplus.com/reference/std/typeinfo/

[]`s

0
source share

All Articles