Qt Remote Objects Compilateur
Aperçu du REPC
Le compilateur de répliques(repc) génère des fichiers d'en-tête QObject sur la base d'un fichier de définition de l'API. Le fichier (appelé fichier "rep") utilise une syntaxe (texte) spécifique pour décrire l'API. Par convention, ces fichiers portent l'extension .rep, abréviation de Replica. Lorsque ces fichiers sont traités par repc, ce dernier génère des fichiers d'en-tête Source et Replica.
Le module Qt Remote Objects comprend également des fonctions CMake et des variables qmake qui peuvent être ajoutées à votre fichier de projet pour exécuter automatiquement repc et ajouter les fichiers résultants à la liste des fichiers traités par Meta-Object Compiler au cours du processus de construction, ce qui simplifie l'utilisation de Qt Remote Objects dans vos projets.
Bien que Qt Remote Objects supporte le partage de n'importe quel QObject sur le réseau (en utilisant enableRemoting du côté de la source et acquireDynamic du côté de la réplique), il y a quelques avantages à laisser repc définir vos objets. Tout d'abord, bien que DynamicReplicas soit utile, il est plus difficile de travailler avec. L'API n'est pas connue tant que l'objet n'est pas initialisé, et l'utilisation de l'API à partir de C++ nécessite des recherches de chaînes de caractères dans les méthodes de QMetaObject. Deuxièmement, le fait de connaître l'interface au moment de la compilation permet de résoudre les problèmes au moment de la compilation plutôt qu'au moment de l'exécution. Troisièmement, le format rep prend en charge les valeurs par défaut, ce qui peut être pratique si vous n'êtes pas en mesure de vous assurer que la source est disponible lorsque la réplique est instanciée.
Voir la documentation ici pour des informations sur l'utilisation des fichiers générés dans votre code. Nous nous concentrerons ici sur le format et les options de repc.
Le format de fichier rep
Le format de fichier rep est un simple langage spécifique à un domaine (DSL ) pour décrire une interface supportée par Qt Remote Objects (QtRO). Comme QtRO est un système basé sur les objets, ces interfaces sont définies par des API disponibles à travers des objets, c'est-à-dire des classes avec des propriétés, des signaux et des slots.
Le type de classe
Chaque classe définie dans un fichier rep devient une QObject dans les fichiers d'en-tête générés, avec l'API décrite générée pour vous.
Pour définir une classe, utilisez le mot-clé class, suivi du nom que vous souhaitez donner à votre type, puis mettez votre API entre parenthèses, comme suit
class MyType { //PROP/CLASS/MODEL/SIGNAL/SLOT/ENUM declarations to define your API };
Lors de l'utilisation des fichiers d'en-tête générés dans une bibliothèque, il peut être nécessaire de définir des attributs de classe pour définir la visibilité des symboles. Cela peut être fait comme en C++ en définissant l'attribut après le mot-clé class. Dans l'exemple suivant, on utilise la macro MYSHAREDLIB_EXPORT, qui est définie dans "mysharedlib_global.h". Voir Création de bibliothèques partagées pour plus d'informations sur ce fonctionnement.
#include "mysharedlib_global.h" class MYSHAREDLIB_EXPORT MyType { ... };
LES ÉLÉMENTS PROP
Q_PROPERTY sont créés en utilisant le mot-clé PROP dans le fichier rep. La syntaxe est la suivante : le mot-clé PROP suivi de la définition entre parenthèses, la définition étant le type, le nom et (éventuellement) une valeur par défaut ou des attributs.
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)
Vous trouverez plus d'informations sur la création de types personnalisés ici.
Par défaut, les propriétés auront des getters et un slot "push" défini, ainsi qu'un signal de notification émis lorsque la valeur est modifiée. Qt Remote Objects nécessite le signal de notification sur l'objet Source pour déclencher l'envoi de mises à jour aux répliques attachées. Dans les versions antérieures de QtRO, les propriétés étaient par défaut en lecture/écriture, c'est-à-dire qu'elles avaient des getters et des setters. Cependant, en raison de la nature asynchrone de QtRO, cela conduisait parfois à un comportement non intuitif. En définissant l'attribut READWRITE sur le PROP, vous retrouverez l'ancien comportement (getter et setter).
// 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
S'il est nécessaire de bloquer jusqu'à ce que la valeur soit modifiée, quelque chose comme ce qui suit est nécessaire.
// 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 utilise maintenant par défaut READPUSH, qui fournit un slot généré automatiquement pour demander un changement de propriété.
// 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)
Vous pouvez également utiliser les mots-clés CONSTANT, READONLY, PERSISTED, READWRITE, READPUSH, ou SOURCEONLYSETTER dans la déclaration PROP, ce qui affecte la façon dont la propriété est mise en œuvre. READPUSH est la valeur par défaut si aucune valeur n'est utilisée.
PROP(int lifeUniverseEverything=42 CONSTANT) PROP(QString name READONLY)
Veuillez noter qu'il y a quelques subtilités ici. Une PROP CONSTANT a une Q_PROPERTY déclarée comme CONSTANT du côté de la SOURCE. Cependant, les répliques ne peuvent pas connaître la valeur correcte avant d'être initialisées, ce qui signifie que la valeur de la propriété doit être autorisée à changer pendant l'initialisation. Pour READONLY, la source n'aura ni setter ni slot push, et le côté réplique n'aura pas de slot push généré. En ajoutant le trait PERSISTED à un PROP, ce dernier utilisera l'instance QRemoteObjectAbstractPersistedStore définie sur un nœud (le cas échéant) pour sauvegarder/restaurer les valeurs du PROP.
Une autre valeur nuancée est SOURCEONLYSETTER, qui fournit une autre façon de spécifier un comportement asymétrique, où la Source (spécifiquement la classe d'aide, SimpleSource) aura un getter et un setter public pour la propriété, mais il sera ReadOnly (avec un signal de notification) du côté Replica. Ainsi, la propriété peut être entièrement contrôlée du côté de la source, mais seulement observée du côté de la réplique. SOURCEONLYSETTER est le mode utilisé par repc pour les instances MODEL et CLASS, ce qui signifie que la source peut modifier l'objet pointé, mais que la réplique ne peut pas fournir un nouvel objet, car aucune méthode set<Prop> ou push<Prop> n'est générée. Notez que cela n'a pas d'incidence sur le comportement des propriétés du type pointé, mais uniquement sur la possibilité de modifier le pointeur lui-même.
CLASSE
Le mot-clé CLASS génère des éléments Q_PROPERTY spéciaux pour les objets dérivés de QObject. Ces propriétés ont la même sémantique que SOURCEONLYSETTER. La syntaxe est la suivante : le mot-clé CLASS suivi du nom de la propriété et du type de sous-objet entre parenthèses.
// In .rep file class OtherClass { PROP(int value) } class MainClass { CLASS subObject(OtherClass) }
MODÈLE
Le mot-clé MODEL génère des éléments spéciaux Q_PROPERTY pour les objets dérivés de QAbstractItemModel. Ces propriétés ont la même sémantique que SOURCEONLYSETTER. La syntaxe est la suivante : le mot-clé MODEL suivi du nom de la propriété, puis des parenthèses entourant les rôles (séparés par des virgules) qui doivent être exposés à la réplique.
// In .rep file class CdClass { PROP(QString title READONLY) MODEL tracks(title, artist, length) }
SIGNAL
Les méthodes designal sont créées en utilisant le mot-clé SIGNAL dans le fichier rep.
L'utilisation consiste à déclarer SIGNAL suivi de la signature souhaitée entre parenthèses. La valeur de retour void doit être ignorée.
SIGNAL(test()) SIGNAL(test(QString foo, int bar)) SIGNAL(test(QMap<QString,int> foo)) SIGNAL(test(const QString &foo)) SIGNAL(test(QString &foo))
queued connectionsTout comme dans Qt XML, les paramètres des signaux qui sont des références seront copiés lorsqu'ils seront transmis aux répliques.
SLOT
Les méthodesSlot sont créées en utilisant le mot-clé SLOT dans le fichier rep.
L'utilisation consiste à déclarer SLOT suivi de la signature souhaitée entre parenthèses. La valeur de retour peut être incluse dans la déclaration. Si la valeur de retour est ignorée, void sera utilisé dans les fichiers générés.
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))
Tout comme dans Qt queued connections et QtRO SIGNALS, les paramètres dans les slots qui sont des références seront copiés lorsqu'ils seront passés aux répliques.
ENUM
Les énumérations (qui utilisent une combinaison de C++ enum et de QtRO Q_ENUM ) sont décrites à l'aide du mot-clé ENUM.
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}Rubriques connexes : Le type ENUM, le mot-clé USE_ENUM
Le type POD
Plain Old Data (POD) est un terme qui décrit une simple collection de données, à l'instar d'une structure C++. Par exemple, si vous avez une API pour un annuaire téléphonique, vous pouvez utiliser le concept d'une "adresse" dans son interface (où l'adresse peut inclure la rue, la ville, l'état, le pays et le code postal). Vous pouvez utiliser le mot-clé POD pour définir des objets de ce type, qui peuvent ensuite être utilisés dans les définitions PROP/SIGNAL/SLOT de vos classes.
L'utilisation consiste à déclarer POD suivi du nom du type généré, suivi des paires de type et de nom séparées par des virgules, les paires de type/nom étant placées entre parenthèses.
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)
Un exemple complet ressemblerait à ceci
Le code généré par repc crée une classe Q_GADGET pour chaque POD, avec des membres Q_PROPERTY correspondants pour chaque type défini pour le POD.
Lors de l'utilisation des fichiers d'en-tête générés dans une bibliothèque, il peut être nécessaire de définir des attributs de classe pour définir la visibilité des symboles. Pour ce faire, il suffit de définir l'attribut après le mot-clé POD. Dans l'exemple suivant, on utilise la macro MYSHAREDLIB_EXPORT, qui est définie dans "mysharedlib_global.h". Voir Création de bibliothèques partagées pour plus d'informations sur ce fonctionnement.
#include "mysharedlib_global.h" POD MYSHAREDLIB_EXPORT Foo(int bar)
Le type ENUM
Il est souvent plus facile et plus propre de définir un ENUM à l'intérieur d'une classe (voir ENUM), mais si vous avez besoin d'un type d'énumération autonome, il peut être utile d'utiliser le mot-clé ENUM en dehors de la définition d'une classe. Cela génère une nouvelle classe dans vos fichiers d'en-tête qui gère le marshalling, etc. La syntaxe est identique à celle de ENUM, à l'exception du fait que la déclaration dans ce cas n'est pas contenue dans une déclaration class.
Sujets connexes : ENUM, mot-clé USE_ENUM
Mot-clé USE_ENUM
Le mot-clé USE_ENUM a été implémenté avant l'ajout de l'autogénération via le mot-clé ENUM. Il est conservé pour des raisons de compatibilité ascendante.
Rubriques connexes : ENUM, Le type ENUM
Directives
Le fichier rep définit une interface, mais les interfaces nécessitent souvent des éléments externes. Pour cela, repc inclura toutes les directives (d'une seule ligne) au début des fichiers générés. Cela vous permet, par exemple, d'utiliser les directives #include ou #define qui supportent la logique ou les types de données nécessaires.
L'outil repc ignore actuellement tout ce qui se trouve entre le symbole "#" et la fin de la ligne et l'ajoute aux fichiers générés. Les instructions #if/#else/#endif sur plusieurs lignes et les macros sur plusieurs lignes ne sont donc pas prises en charge.
Directives #HEADER et #FOOTER
Il existe deux directives spéciales, #HEADER et #FOOTER. Ces directives peuvent être utilisées pour définir le contenu qui doit être placé tel quel dans le code généré, soit avant (HEADER), soit après (FOOTER) la déclaration des interfaces. Les tokens de tête #HEADER et #FOOTER ainsi qu'un caractère d'espacement sont supprimés.
Dans l'exemple suivant, les classes repc générées sont placées dans un espace de noms.
#HEADER namespace MyNamespace { class MyType { ... }; #FOOTER } // namespace MyNamespace
Fonctions CMake
Les fonctions CMake permettant de générer des types de sources et de répliques sont énumérées ci-dessous.
Crée des fichiers d'en-tête C++ pour les types source et réplique à partir des fichiers .rep ( Qt Remote Objects ). | |
Création de fichiers d'en-tête C++ pour les types de répliques à partir des fichiers Qt Remote Objects.rep. | |
Création de fichiers d'en-tête C++ pour les types de sources à partir des fichiers .rep de Qt Remote Objects. | |
Crée des fichiers .rep à partir des fichiers d'en-tête QObject. |
Variables qmake
REPC_REPLICA
Spécifie les noms de tous les fichiers rep du projet qui doivent être utilisés pour générer des fichiers d'en-tête répliqués.
Par exemple :
REPC_REPLICA = media.rep \ location.rep
Le(s) fichier(s) généré(s) sera(ont) de la forme rep_<replica file base>_replica.h.
REPC_SOURCE
Spécifie les noms de tous les fichiers rep du projet qui doivent être utilisés pour générer des fichiers d'en-tête source.
Par exemple :
REPC_SOURCE = media.rep \ location.rep
Le(s) fichier(s) généré(s) sera(ont) de la forme rep_<replica file base>_source.h.
REPC_MERGED
Spécifie les noms de tous les fichiers rep du projet qui doivent être utilisés pour générer des fichiers d'en-tête combinés (source et réplique).
Par exemple :
REPC_MERGED = media.rep \ location.rep
Le(s) fichier(s) généré(s) sera(ont) de la forme rep_<replica file base>_merged.h.
Remarque : en règle générale, les sources et les répliques se trouvent dans des processus ou des périphériques distincts, c'est pourquoi cette variable n'est pas couramment utilisée.
QOBJECT_REP
Spécifie les noms des fichiers d'en-tête QObject existants qui doivent être utilisés pour générer les fichiers .rep correspondants.
Voir également 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.