325 Stimmen

Wie kann ich Reflection zu einer C++-Anwendung hinzufügen?

Ich möchte in der Lage sein, eine C++-Klasse auf ihren Namen, ihren Inhalt (d.h. Mitglieder und ihre Typen) usw. zu untersuchen. Ich spreche hier von nativem C++, nicht von verwaltetem C++, das Reflection hat. Ich weiß, dass C++ mit RTTI einige begrenzte Informationen liefert. Welche zusätzlichen Bibliotheken (oder andere Techniken) könnten diese Informationen liefern?

21 Stimmen

Pech gehabt, ohne Makros und andere Vorverarbeitungen geht es nicht, denn die erforderlichen Metadaten gibt es nicht es sei denn, Sie erstellen sie manuell mit Hilfe von Makro-Vorverarbeitungsmagie.

7 Stimmen

Die Informationen, die Sie von RTTI erhalten können, reichen jedoch nicht aus, um die meisten Dinge zu tun, für die Sie eigentlich eine Reflexion benötigen würden. Sie können zum Beispiel nicht über die Mitgliedsfunktionen einer Klasse iterieren.

5voto

Germán Diago Punkte 7087

EDIT: Aktualisierter fehlerhafter Link vom 7. Februar 2017.

Ich glaube, das hat noch niemand erwähnt:

Am CERN wird ein vollständiges Reflexionssystem für C++ verwendet:

CERN-Reflex . Es scheint sehr gut zu funktionieren.

0 Stimmen

@j4nbur53 Der Link ist kaputt, weil es scheint, dass sie einen Meilenstein erreicht haben: Root.cern.ch

0 Stimmen

Könnte es sein, dass Sie diesen Link meinen Root.cern.ch/Root/doc/ROOTUsersGuideHTML/ch07.html Kapitel Reflex?

0 Stimmen

Versuchen Sie dies Root.cern.ch/wie/wie-den-reflex-verwenden . Reflex arbeitet als ein Generator, der Ihre Header-Dateien analysiert und C++ Introspektionscode/Bibliothek generiert, die Sie mit einer einfachen API verknüpfen und verwenden können.

5voto

Ira Baxter Punkte 91118

Bei der Reflexion geht es im Wesentlichen darum, was der Compiler als Fußspuren im Code hinterlassen hat, die der Laufzeitcode abfragen kann. C++ ist bekannt dafür, dass man nicht für das bezahlt, was man nicht benutzt; da die meisten Leute Reflection nicht benutzen/wünschen, vermeidet der C++-Compiler die Kosten, indem er nicht aufzeichnet alles .

C++ bietet also keine Reflexion, und es ist nicht einfach, sie selbst als allgemeine Regel zu "simulieren", wie in anderen Antworten festgestellt wurde.

Unter "andere Techniken", wenn Sie keine Sprache mit Reflexion haben, ein Werkzeug, das die gewünschten Informationen zur Kompilierzeit extrahieren kann.

Unser DMS-Software-Reengineering-Werkzeugsatz ist eine verallgemeinerte Compilertechnologie, die durch explizite Sprachdefinitionen parametrisiert wird. Sie hat Sprachdefinitionen für C, C++, Java, COBOL, PHP, ...

Für C-, C++-, Java- und COBOL-Versionen bietet es vollständigen Zugriff auf Parse-Bäume und Symboltabelleninformationen. Diese Symboltabelleninformationen umfassen die Art von Daten, die Sie wahrscheinlich von "reflection" erwarten. Wenn Ihr Ziel darin besteht, eine Reihe von Feldern oder Methoden aufzuzählen und hacer etwas mit ihnen anzufangen, kann DMS verwendet werden, um den Code entsprechend dem, was in den Symboltabellen steht, auf beliebige Weise umzuwandeln.

3voto

alariq Punkte 506

Eine weitere Bibliothek finden Sie hier: http://www.garret.ru/cppreflection/docs/reflect.html Es unterstützt 2 Möglichkeiten: Typinformationen aus den Debug-Informationen zu erhalten und dem Programmierer zu erlauben, diese Informationen bereitzustellen.

Ich interessiere mich auch für Reflexion für mein Projekt und fand diese Bibliothek, ich habe es noch nicht versucht, aber versucht, andere Werkzeuge von diesem Kerl und ich mag, wie sie funktionieren :-)

3voto

TarmoPikaro Punkte 4208

Wenn Sie auf der Suche nach relativ einfachen C++ Reflexion - Ich habe aus verschiedenen Quellen Makro / Defines gesammelt, und kommentiert sie aus, wie sie funktioniert. Sie können die Header Dateien von hier herunterladen:

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

Satz von Definitionen und darüber hinausgehende Funktionen:

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

Die Beispielanwendung befindet sich ebenfalls im Git-Repository, und zwar hier: https://github.com/tapika/TestCppReflect/

Ich kopiere ihn hier teilweise mit Erläuterungen:

#include "CppReflect.h"
using namespace std;

class Person
{
public:

    // Repack your code into REFLECTABLE macro, in (<C++ Type>) <Field name>
    // 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 verwendet Klassenname + Feldname mit offsetof - um festzustellen, an welcher Stelle im Speicher sich ein bestimmtes Feld befindet. Ich habe versucht, die .NET-Terminologie so weit wie möglich zu übernehmen, aber C++ und C# sind unterschiedlich, daher ist es nicht 1 zu 1. Das gesamte C++-Reflexionsmodell befindet sich in TypeInfo y FieldInfo Klassen.

Ich habe pugi xml parser verwendet, um Demo-Code in xml zu holen und es zurück von xml wiederherzustellen.

Die Ausgabe des Democodes sieht also wie folgt aus:

<?xml version="1.0" encoding="utf-8"?>
<People groupName="Group1">
    <people>
        <Person name="Roger" age="37" />
        <Person name="Alice" age="27" />
        <Person name="Cindy" age="17" />
    </people>
</People>

Es ist auch möglich, eine beliebige Klasse/Struktur von Drittanbietern über die TypeTraits-Klasse und eine partielle Template-Spezifikation zu aktivieren - um Ihre eigene TypeTraitsT-Klasse zu definieren, ähnlich wie bei CString oder int - siehe Beispielcode in

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

Diese Lösung ist für Windows / Visual Studio geeignet. Es ist möglich, sie auf andere Betriebssysteme/Compiler zu portieren, aber das habe ich nicht getan. (Fragen Sie mich, wenn Sie wirklich wie Lösung, ich könnte in der Lage sein, Ihnen zu helfen)

Diese Lösung ist für die einmalige Serialisierung einer Klasse mit mehreren Unterklassen geeignet.

Wenn Sie jedoch nach einem Mechanismus suchen, um Klassenteile zu serialisieren oder sogar zu kontrollieren, welche Funktionalität Reflection-Aufrufe erzeugen, können Sie sich die folgende Lösung ansehen:

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

Ausführlichere Informationen finden Sie in einem youtube-Video:

C++ Laufzeittyp-Reflexion https://youtu.be/TN8tJijkeFE

Ich versuche, etwas genauer zu erklären, wie die C++-Reflexion funktioniert.

Der Beispielcode sieht zum Beispiel so aus:

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;

Aber jeder Schritt hier führt tatsächlich zu einem Funktionsaufruf Verwendung von C++-Eigenschaften mit __declspec(property(get =, put ... ) .

die vollständige Informationen über C++-Datentypen, C++-Eigenschaftsnamen und Klasseninstanzzeiger in Form von Pfaden erhält, und auf der Grundlage dieser Informationen können Sie xml, json erzeugen oder sogar über das Internet serialisieren.

Beispiele für solche virtuellen Callback-Funktionen finden Sie hier:

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

Siehe Funktionen ReflectCopy und die virtuelle Funktion ::OnAfterSetProperty .

Da das Thema jedoch sehr fortgeschritten ist, empfehle ich, sich zuerst das Video anzusehen.

Wenn Sie Verbesserungsvorschläge haben, können Sie mich gerne kontaktieren.

2voto

Bohdan Punkte 14977

Es sieht so aus, als ob C++ immer noch nicht über diese Funktion verfügt. Und C++11 auch die Reflexion verschoben ((

Suchen Sie einige Makros oder erstellen Sie eigene. Qt kann auch mit Reflexion helfen (wenn es verwendet werden kann).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X