Auf dieser Seite

Qt Remote Objects Compiler

REPC-Übersicht

Der Replica -Compiler(repc) generiert „ QObject “-Header-Dateien auf der Grundlage einer API-Definitionsdatei. Die Datei (eine sogenannte „rep“-Datei) verwendet eine spezifische (Text-)Syntax zur Beschreibung der API. Gemäß Konvention erhalten diese Dateien die Dateiendung .rep, kurz für „Replica“. Wenn diese Dateien von repc verarbeitet werden, generiert repc sowohl Source- als auch Replica -Header-Dateien.

Das „ Qt Remote Objects “-Modul enthält außerdem CMake-Funktionen und qmake-Variablen, die Ihrer Projektdatei hinzugefügt werden können, um repc automatisch auszuführen und die resultierenden Dateien der Liste der vom Meta-Object Compiler während des Build-Prozesses verarbeiteten Dateien hinzuzufügen, wodurch die Verwendung von „ Qt Remote Objects “ in Ihren Projekten vereinfacht wird.

Zwar unterstützt „ Qt Remote Objects “ die gemeinsame Nutzung beliebiger „ QObject “ über das Netzwerk (mithilfe von „enableRemoting“ auf der „Source“-Seite und „acquireDynamic“ auf der „Replica“-Seite), doch bietet es einige Vorteile, wenn Sie Ihre Objekte von „repc“ definieren lassen. Erstens sind „ DynamicReplicas “ zwar nützlich, ihre Handhabung ist jedoch umständlicher. Die API ist erst nach der Initialisierung des Objekts bekannt, und die Verwendung der API aus C++ erfordert String-Lookups über die Methoden von „ QMetaObject “. Zweitens werden durch die Bekanntheit der Schnittstelle bereits zur Kompilierungszeit eventuelle Probleme erkannt, anstatt erst zur Laufzeit. Drittens unterstützt das REP-Format Standardwerte, was praktisch sein kann, wenn Sie nicht sicherstellen können, dass die Quelle bei der Instanziierung der Replik verfügbar ist.

Informationen zur Verwendung der generierten Dateien in Ihrem Code finden Sie in der Dokumentation hier. Hier konzentrieren wir uns auf das repc-Format und die Optionen.

Das „rep“-Dateiformat

Das „rep“-Dateiformat ist eine einfache domänenspezifische Sprache (DSL) zur Beschreibung einer Schnittstelle, die über „ Qt Remote Objects “ (QtRO) unterstützt wird. Da QtRO ein objektbasiertes System ist, werden diese Schnittstellen durch APIs definiert, die über Objekte verfügbar sind, d. h. Klassen mit Eigenschaften, Signalen und Slots.

Kommentare

Es werden sowohl einzeilige Kommentare im C++-Stil (// text ) als auch mehrzeilige Kommentare im C-Stil (/* text * / ) unterstützt.

Der Klassentyp

Jede in einer REP-Datei definierte Klasse wird in den generierten Header-Dateien zu einem ` QObject `, wobei die beschriebene API für Sie generiert wird.

Um eine Klasse zu definieren, verwenden Sie das Schlüsselwort „ class “, gefolgt von dem gewünschten Namen für Ihren Typ, und schließen Sie Ihre API anschließend wie folgt in Klammern ein

class MyType
{
    //PROP/CLASS/MODEL/SIGNAL/SLOT/ENUM declarations to define your API
};

Wenn Sie die generierten Header-Dateien innerhalb einer Bibliothek verwenden, kann es erforderlich sein, Klassenattribute zu definieren, um die Sichtbarkeit der Symbole festzulegen. Dies kann ähnlich wie in C++ erfolgen, indem das Attribut nach dem Schlüsselwort „ class “ definiert wird. Im folgenden Beispiel wird das Makro „ MYSHAREDLIB_EXPORT “ verwendet, das in „ "mysharedlib_global.h" “ definiert ist. Weitere Informationen zur Funktionsweise finden Sie unter „Erstellen von gemeinsam genutzten Bibliotheken “.

#include "mysharedlib_global.h"
class MYSHAREDLIB_EXPORT MyType
{
    ...
};

PROP

Q_PROPERTY -Elemente werden mithilfe des Schlüsselworts „PROP“ in der REP-Datei erstellt. Die Syntax besteht aus dem Schlüsselwort „ PROP “, gefolgt von der in Klammern eingeschlossenen Definition, wobei die Definition aus dem Typ, dem Namen und (optional) einem Standardwert oder Attributen besteht.

PROP(bool simpleBool)                // boolean named simpleBool
PROP(bool defaultFalseBool=false)    // boolean named defaultFalseBool, with false
                                     // as the default value

PROP(int lifeUniverseEverything=42)  // int value that defaults to 42
PROP(QByteArray myBinaryInfo)        // Qt types are fine, may need #include
                                     // additional headers in your rep file

PROP(QString name CONSTANT)          // Property with the CONSTANT attribute
PROP(QString setable READWRITE)      // Property with the READWRITE attribute
                                     // note: Properties default to READPUSH
                                     // (see description below)

PROP(SomeOtherType myCustomType)     // Custom types work. Needs #include for the
                                     // appropriate header for your type, make
                                     // sure your type is known to the metabject
                                     // system, and make sure it supports Queued
                                     // Connections (see Q_DECLARE_METATYPE and
                                     // qRegisterMetaType)

Weitere Informationen zum Erstellen benutzerdefinierter Typen finden Sie hier.

Standardmäßig verfügen Eigenschaften über Getter und einen definierten „push“-Slot sowie ein „notify“-Signal, das bei einer Wertänderung ausgelöst wird. „ Qt Remote Objects “ benötigt das „notify“-Signal am Source-Objekt, um das Senden von Aktualisierungen an die verbundenen Replikate auszulösen. In früheren Versionen von QtRO waren Eigenschaften standardmäßig schreib- und lesbar, d. h., sie verfügten über Getter und Setter. Aufgrund der asynchronen Natur von QtRO führte dies jedoch gelegentlich zu unintuitivem Verhalten. Durch Setzen des READWRITE-Attributs am PROP wird das alte Verhalten (Getter und Setter) wiederhergestellt.

// In .rep file, old (setter) behavior
PROP(int myVal READWRITE)             // Old behavior with setMyVal(int myVal) method

// In code...  Assume myVal is initially set to 0 in Source
int originalValue = rep->myVal();     // Will be 0
rep->setMyVal(10);                    // Call setter, expecting a blocking/
                                      // non-asynchronous return

if (rep->myVal() == 10) ...           // Test will usually fail

Wenn es erforderlich ist, so lange zu warten, bis der Wert geändert wurde, ist eine Umsetzung wie die folgende notwendig.

// In .rep file, old (setter) behavior
PROP(int myVal READWRITE)             // Old behavior with setMyVal(int myVal) method

// In code...  Assume myVal is initially set to 0 in Source
bool originalValue = rep->myVal();    // Will be 0

// We can wait for the change using \l QSignalSpy
QSignalSpy spy(rep, SIGNAL(myValChanged(int)));

rep->setMyVal(10);                    // Call setter, expecting a blocking/
                                      // non-asynchronous return

spy.wait();                           // spy.wait() blocks until changed signal
                                      // is received
if (rep->myVal() == 10) ...           // Test will succeed assuming
                                      // 1. Source object is connected
                                      // 2. Nobody else (Source or other Replica)
                                      //    sets the myVal to something else (race
                                      //    condition)
// Rather than use QSignalSpy, the event-driven practice would be to connect the
// myValChanged notify signal to a slot that responds to the changes.

QtRO verwendet nun standardmäßig „READPUSH“, wodurch ein automatisch generierter Slot für die Anforderung einer Eigenschaftsänderung bereitgestellt wird.

// In .rep file, defaults to READPUSH
PROP(bool myVal)                      // No setMyVal(int myVal) on Replica, has
                                      // pushMyVal(int myVal) instead

// In code...  Assume myVal is initially set to 0 in Source
bool originalValue = rep->myVal();    // Will be 0

// We can wait for the change using \l QSignalSpy
QSignalSpy spy(rep, SIGNAL(myValChanged(int)));

rep->pushMyVal(10);                   // Call push method, no expectation that change
                                      // is applied upon method completion.

// Some way of waiting for change to be received by the Replica is still necessary,
// but hopefully not a surprise with the new pushMyVal() Slot.
spy.wait();                           // spy.wait() blocks until changed signal
                                      // is received
if (rep->myVal() == 10) ...           // Test will succeed assuming
                                      // 1. Source object is connected
                                      // 2. Nobody else (Source or other Replica)
                                      //    set the myVal to something else (race
                                      //    condition)

Sie können in der PROP-Deklaration auch die Schlüsselwörter „ CONSTANT “, „ READONLY “, „ PERSISTED “, „ READWRITE “, „ READPUSH “ oder „ SOURCEONLYSETTER “ verwenden, die Einfluss darauf haben, wie die Eigenschaft implementiert wird. „READPUSH“ ist der Standardwert, wenn kein Wert angegeben wird.

PROP(int lifeUniverseEverything=42 CONSTANT)
PROP(QString name READONLY)

Bitte beachten Sie, dass es hier einige Feinheiten gibt. Eine CONSTANT-PROP verfügt auf der SOURCE-Seite über ein als CONSTANT deklariertes „ Q_PROPERTY “. Replikate können den korrekten Wert jedoch erst nach ihrer Initialisierung kennen, was bedeutet, dass sich der Eigenschaftswert während der Initialisierung ändern darf. Bei READONLY verfügt die Quelle weder über einen Setter noch über einen Push-Slot, und auf der Replikseite wird kein Push-Slot generiert. Durch Hinzufügen des Traits PERSISTED zu einer PROP nutzt diese die auf einem Knoten festgelegte „ QRemoteObjectAbstractPersistedStore “-Instanz (sofern vorhanden), um PROP-Werte zu speichern bzw. wiederherzustellen.

Ein weiterer nuancierter Wert ist „SOURCEONLYSETTER“, der eine weitere Möglichkeit zur Festlegung asymmetrischen Verhaltens bietet: Dabei verfügt die Quelle (insbesondere die Hilfsklasse „ SimpleSource “) über einen öffentlichen Getter und Setter für die Eigenschaft, während diese auf der Replikseite als „ReadOnly“ (mit einem „notify“-Signal) definiert ist. Somit kann die Eigenschaft von der Quellseite aus vollständig gesteuert, von der Replikseite aus jedoch nur beobachtet werden. „SOURCEONLYSETTER“ ist der von repc für „MODEL“- und „CLASS“-Instanzen verwendete Modus. Das bedeutet, dass die Quelle das Objekt, auf das verwiesen wird, ändern kann, die Replik jedoch kein neues Objekt bereitstellen kann, da keine „set<Prop>“- oder „push<Prop>“-Methode generiert wird. Beachten Sie, dass dies keinen Einfluss auf das Verhalten der Eigenschaften des referenzierten Typs hat, sondern lediglich auf die Möglichkeit, den Zeiger selbst zu ändern.

CLASS

Das Schlüsselwort „CLASS“ generiert spezielle „ Q_PROPERTY “-Elemente für Objekte, die von „ QObject “ abgeleitet sind. Diese Eigenschaften haben dieselbe Semantik wie „SOURCEONLYSETTER“. Die Syntax besteht aus dem Schlüsselwort „ CLASS “, gefolgt vom Eigenschaftsnamen und anschließend dem Typ des Teilobjekts in Klammern.

// In .rep file
class OtherClass
{
    PROP(int value)
}

class MainClass
{
    CLASS subObject(OtherClass)
}

MODEL

Das Schlüsselwort MODEL generiert spezielle „ Q_PROPERTY “-Elemente für Objekte, die von „ QAbstractItemModel “ abgeleitet sind. Diese Eigenschaften haben dieselbe Semantik wie SOURCEONLYSETTER. Die Syntax besteht aus dem Schlüsselwort „ MODEL “, gefolgt vom Eigenschaftsnamen und anschließend Klammern, die die (durch Kommas getrennten) Rollen umschließen, die der Replik offengelegt werden sollen.

// In .rep file
class CdClass
{
    PROP(QString title READONLY)
    MODEL tracks(title, artist, length)
}

SIGNAL

Signalmethoden werden mithilfe des Schlüsselworts SIGNAL in der REP-Datei erstellt.

Zur Verwendung wird „ SIGNAL “ deklariert, gefolgt von der gewünschten Signatur in Klammern. Der Rückgabewert vom Typ „void“ sollte weggelassen werden.

SIGNAL(test())
SIGNAL(test(QString foo, int bar))
SIGNAL(test(QMap<QString,int> foo))
SIGNAL(test(const QString &foo))
SIGNAL(test(QString &foo))

queued connectionsGenau wie bei Qt XML-ph-0000@deepl.internal werden Parameter in Signalen, die Referenzen sind, bei der Übergabe an Replikate kopiert.

SLOT

Slot-Methoden werden mithilfe des Schlüsselworts „SLOT“ in der rep-Datei erstellt.

Zur Verwendung deklariert man „ SLOT “, gefolgt von der gewünschten Signatur in Klammern. Der Rückgabewert kann in die Deklaration aufgenommen werden. Wird der Rückgabewert weggelassen, wird in den generierten Dateien „void“ verwendet.

SLOT(test())
SLOT(void test(QString foo, int bar))
SLOT(test(QMap<QString,int> foo))
SLOT(test(QMap<QString,int> foo, QMap<QString,int> bar))
SLOT(test(QMap<QList<QString>,int> foo))
SLOT(test(const QString &foo))
SLOT(test(QString &foo))
SLOT(test(const QMap<QList<QString>,int> &foo))
SLOT(test(const QString &foo, int bar))

queued connections Genau wie bei Qt XML-ph-0000@deepl.internal und QtRO-SIGNALS werden Parameter in Slots, die Referenzen sind, bei der Übergabe an Replikate kopiert.

ENUM

Aufzählungen (die eine Kombination aus C++-enum und Qt- Q_ENUM in QtRO verwenden) werden mit dem Schlüsselwort ENUM beschrieben.

ENUM MyEnum {Foo}
ENUM MyEnum {Foo, Bar}
ENUM MyEnum {Foo, Bar = -1}
ENUM MyEnum {Foo=-1, Bar}
ENUM MyEnum {Foo=0xf, Bar}
ENUM MyEnum {Foo=1, Bar=3, Bas=5}

Verwandte Themen: Der ENUM-Typ, das Schlüsselwort USE_ENUM

Der POD-Typ

„Plain Old Data“ (POD) ist ein Begriff, der eine einfache Datensammlung im Sinne einer C++-Struktur beschreibt. Wenn Sie beispielsweise eine API für ein Telefonbuch haben, möchten Sie vielleicht das Konzept einer „Adresse“ in deren Schnittstelle verwenden (wobei eine Adresse Straße, Stadt, Bundesland, Land und Postleitzahl umfassen könnte). Mit dem Schlüsselwort „POD“ können Sie Objekte dieser Art definieren, die dann in PROP-/SIGNAL-/SLOT-Definitionen in Ihren Klassendefinitionen verwendet werden können.

Die Verwendung erfolgt durch die Deklaration „ POD “, gefolgt vom Namen des generierten Typs und anschließend von durch Kommas getrennten Typ-Namen-Paaren, wobei die Typ-Namen-Paare in Klammern stehen.

POD Foo(int bar)
POD Foo(int bar, double bas)
POD Foo(QMap<QString,int> bar)
POD Foo(QList<QString> bar)
POD Foo(QMap<QString,int> bar, QMap<double,int> bas)

Ein vollständiges Beispiel würde wie folgt aussehen

POD Foo(QList<QString> bar)
class MyType
{
    SIGNAL(sendCustom(Foo foo));
};

Der von repc generierte Code erstellt für jedes POD eine „ Q_GADGET “-Klasse mit entsprechenden „ Q_PROPERTY “-Mitgliedern für jeden für das POD definierten Typ.

Bei der Verwendung der generierten Header-Dateien innerhalb einer Bibliothek kann es erforderlich sein, Klassenattribute zu definieren, um die Sichtbarkeit der Symbole festzulegen. Dies kann durch die Definition des Attributs nach dem Schlüsselwort „ POD “ erfolgen. Im folgenden Beispiel wird das Makro „ MYSHAREDLIB_EXPORT “ verwendet, das in „ "mysharedlib_global.h" “ definiert ist. Weitere Informationen zur Funktionsweise finden Sie unter „Erstellen von gemeinsam genutzten Bibliotheken “.

#include "mysharedlib_global.h"
POD MYSHAREDLIB_EXPORT Foo(int bar)

Der ENUM-Typ

Oft ist es einfacher und übersichtlicher, eine ENUM innerhalb einer Klasse zu definieren (siehe ENUM), doch wenn Sie einen eigenständigen ENUM-Typ benötigen, kann die Verwendung des Schlüsselworts „ENUM“ außerhalb einer Klassendefinition hilfreich sein. Dadurch wird in Ihren Header-Dateien eine neue Klasse generiert, die sich um das Marshalling usw. kümmert. Die Syntax ist identisch mit der von ENUM, mit der Ausnahme, dass die Deklaration in diesem Fall nicht in einer „ class “-Deklaration enthalten ist.

Verwandte Themen: ENUM, Schlüsselwort USE_ENUM

Schlüsselwort USE_ENUM

Das Schlüsselwort USE_ENUM wurde implementiert, bevor die automatische Generierung über das Schlüsselwort ENUM hinzugefügt wurde. Es wird aus Gründen der Abwärtskompatibilität beibehalten.

Verwandte Themen: ENUM, Der Typ ENUM

Direktiven

Die REP-Datei definiert eine Schnittstelle, doch Schnittstellen erfordern oft externe Elemente. Um dies zu unterstützen, fügt repc alle (einzeiligen) Direktiven am Anfang der generierten Dateien ein. So können Sie beispielsweise #include- oder #define-Direktiven verwenden, die die benötigte Logik oder die erforderlichen Datentypen unterstützen.

Das repc-Tool ignoriert derzeit alles vom Symbol „#“ bis zum Zeilenende und fügt diesen Teil in die generierten Dateien ein. Daher werden mehrzeilige #if/#else/#endif-Anweisungen und mehrzeilige Makros nicht unterstützt.

Es gibt zwei spezielle Direktiven: „ #HEADER “ und „ #FOOTER “. Mit diesen Direktiven lässt sich Inhalt definieren, der unverändert in den generierten Code übernommen werden soll – entweder vor (HEADER) oder nach (FOOTER) der Schnittstellendeklaration. Die führenden Token „ #HEADER “ und „ #FOOTER “ sowie ein Leerzeichen werden entfernt.

Im folgenden Beispiel werden die generierten repc-Klassen in einen Namespace eingefügt.

#HEADER namespace MyNamespace {
class MyType
{
    ...
};
#FOOTER } // namespace MyNamespace

CMake-Funktionen

Die CMake-Funktionen zur Generierung von Quell- und Replikat-Typen sind im Folgenden aufgeführt.

qt_add_repc_merged

Erstellt C++-Header-Dateien für Quell- und Replikat-Typen aus den „ Qt Remote Objects “-.rep-Dateien.

qt_add_repc_replicas

Erstellt C++-Header-Dateien für Replikat-Typen aus den „ Qt Remote Objects “-.rep-Dateien.

qt_add_repc_sources

Erstellt C++-Header-Dateien für Quelltypen aus den „ Qt Remote Objects “-.rep-Dateien.

qt_reps_from_headers

Erstellt .rep-Dateien aus den QObject-Header-Dateien.

qmake-Variablen

REPC_REPLICA

Gibt die Namen aller .rep-Dateien im Projekt an, die zur Generierung von Replika-Header-Dateien verwendet werden sollen.

Beispiel:

REPC_REPLICA = media.rep \
               location.rep

Die generierten Dateien haben das Format „ rep_<replica file base>_replica.h “.

REPC_SOURCE

Gibt die Namen aller rep-Dateien im Projekt an, die zur Generierung von Quell-Header-Dateien verwendet werden sollen.

Beispiel:

REPC_SOURCE = media.rep \
              location.rep

Die generierten Dateien haben die Form rep_<replica file base>_source.h.

REPC_MERGED

Gibt die Namen aller REP-Dateien im Projekt an, die zur Erstellung kombinierter (Quell- und Replikat-)Header-Dateien verwendet werden sollen.

Beispiel:

REPC_MERGED = media.rep \
              location.rep

Die generierten Dateien haben die Form „ rep_<replica file base>_merged.h “.

Hinweis: Da sich Quellen und Replikatein der Regel in getrennten Prozessen oder auf unterschiedlichen Geräten befinden, wird diese Variable normalerweise nicht verwendet.

QOBJECT_REP

Gibt die Namen vorhandener „ QObject “-Header-Dateien an, die zur Erstellung entsprechender .rep-Dateien verwendet werden sollen.

Siehe auch „ QRemoteObjectAbstractPersistedStore “.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.