How can I add reflection to a C++ application?

前端 未结 28 2344
感动是毒
感动是毒 2020-11-21 11:25

I\'d like to be able to introspect a C++ class for its name, contents (i.e. members and their types) etc. I\'m talking native C++ here, not managed C++, which has reflection

28条回答
  •  生来不讨喜
    2020-11-21 11:57

    If you're looking for relatively simple C++ reflection - I have collected from various sources macro / defines, and commented them out how they works. You can download header files from here:

    https://github.com/tapika/TestCppReflect/blob/master/MacroHelpers.h

    set of defines, plus functionality on top of it:

    https://github.com/tapika/TestCppReflect/blob/master/CppReflect.h https://github.com/tapika/TestCppReflect/blob/master/CppReflect.cpp https://github.com/tapika/TestCppReflect/blob/master/TypeTraits.h

    Sample application resides in git repository as well, in here: https://github.com/tapika/TestCppReflect/

    I'll partly copy it here with explanation:

    #include "CppReflect.h"
    using namespace std;
    
    
    class Person
    {
    public:
    
        // Repack your code into REFLECTABLE macro, in () 
        // form , like this:
    
        REFLECTABLE( Person,
            (CString)   name,
            (int)       age,
    ...
        )
    };
    
    void main(void)
    {
        Person p;
        p.name = L"Roger";
        p.age = 37;
    ...
    
        // And here you can convert your class contents into xml form:
    
        CStringW xml = ToXML( &p );
        CStringW errors;
    
        People ppl2;
    
        // And here you convert from xml back to class:
    
        FromXml( &ppl2, xml, errors );
        CStringA xml2 = ToXML( &ppl2 );
        printf( xml2 );
    
    }
    

    REFLECTABLE define uses class name + field name with offsetof - to identify at which place in memory particular field is located. I have tried to pick up .NET terminology for as far as possible, but C++ and C# are different, so it's not 1 to 1. Whole C++ reflection model resides in TypeInfo and FieldInfo classes.

    I have used pugi xml parser to fetch demo code into xml and restore it back from xml.

    So output produced by demo code looks like this:

    
    
        
            
            
            
        
    
    

    It's also possible to enable any 3-rd party class / structure support via TypeTraits class, and partial template specification - to define your own TypeTraitsT class, in similar manner to CString or int - see example code in

    https://github.com/tapika/TestCppReflect/blob/master/TypeTraits.h#L195

    This solution is applicable for Windows / Visual studio. It's possible to port it to other OS/compilers, but haven't done that one. (Ask me if you really like solution, I might be able to help you out)

    This solution is applicable for one shot serialization of one class with multiple subclasses.

    If you however are searching for mechanism to serialize class parts or even to control what functionality reflection calls produce, you could take a look on following solution:

    https://github.com/tapika/cppscriptcore/tree/master/SolutionProjectModel

    More detailed information can be found from youtube video:

    C++ Runtime Type Reflection https://youtu.be/TN8tJijkeFE

    I'm trying to explain bit deeper on how c++ reflection will work.

    Sample code will look like for example this:

    https://github.com/tapika/cppscriptcore/blob/master/SolutionProjectModel/testCppApp.cpp

    c.General.IntDir = LR"(obj\$(ProjectName)_$(Configuration)_$(Platform)\)";
    c.General.OutDir = LR"(bin\$(Configuration)_$(Platform)\)";
    c.General.UseDebugLibraries = true;
    c.General.LinkIncremental = true;
    c.CCpp.Optimization = optimization_Disabled;
    c.Linker.System.SubSystem = subsystem_Console;
    c.Linker.Debugging.GenerateDebugInformation = debuginfo_true;
    

    But each step here actually results in function call Using C++ properties with __declspec(property(get =, put ... ).

    which receives full information on C++ Data Types, C++ property names and class instance pointers, in form of path, and based on that information you can generate xml, json or even serialize that one over internet.

    Examples of such virtual callback functions can be found here:

    https://github.com/tapika/cppscriptcore/blob/master/SolutionProjectModel/VCConfiguration.cpp

    See functions ReflectCopy, and virtual function ::OnAfterSetProperty.

    But since topic is really advanced - I recommend to check through video first.

    If you have some improvement ideas, feel free to contact me.

提交回复
热议问题