En esta página

Qt Remote Objects Compilador

Visión general de REPC

El compilador de réplicas(repc) genera archivos de cabecera QObject basados en un archivo de definición de API. El archivo (denominado archivo "rep") utiliza una sintaxis (de texto) específica para describir la API. Por convención, estos archivos tienen una extensión .rep, abreviatura de Replica. Cuando estos archivos son procesados por repc, éste genera tanto los archivos de cabecera de la fuente como los de la réplica.

El módulo Qt Remote Objects también incluye funciones CMake y variables qmake que pueden ser añadidas a tu archivo de proyecto para ejecutar automáticamente repc, y añadir los archivos resultantes a la lista de archivos procesados por Meta Object Compiler durante el proceso de construcción, haciendo simple el uso de Qt Remote Objects en tus proyectos.

Mientras que Qt Remote Objects soporta compartir cualquier QObject a través de la red (usando enableRemoting en el lado Fuente y acquireDynamic en el lado Réplica), hay un par de ventajas en dejar que repc defina tus objetos. En primer lugar, aunque DynamicReplicas es útil, es más engorroso trabajar con ellos. La API no se conoce hasta que se inicializa el objeto, y utilizar la API desde C++ requiere búsquedas de cadenas a través de los métodos de QMetaObject. En segundo lugar, el hecho de que la interfaz se conozca en tiempo de compilación permite detectar cualquier problema en tiempo de compilación frente a en tiempo de ejecución. En tercer lugar, el formato rep admite valores por defecto, lo que puede ser útil si no puede asegurarse de que la fuente esté disponible cuando se instancie la réplica.

Consulte la documentación aquí para obtener información sobre el uso de los archivos generados en su código. Aquí nos centraremos en el formato repc y sus opciones.

El formato de archivo rep

El formato de archivo rep es un Lenguaje Específico de Dominio (DSL) simple para describir una interfaz soportada sobre Qt Remote Objects (QtRO). Dado que QtRO es un sistema basado en objetos, estas interfaces se definen mediante APIs disponibles a través de objetos, es decir, clases con propiedades, señales y ranuras.

El tipo de clase

Cada clase definida en un archivo rep se convierte en un QObject en los archivos de cabecera generados, con la API descrita generada para usted.

Para definir una clase, utilice la palabra clave class, seguida del nombre que desee para su tipo y, a continuación, encierre su API entre paréntesis de la siguiente manera

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

Al utilizar los archivos de cabecera generados dentro de una biblioteca, puede ser necesario definir atributos de clase para establecer la visibilidad de los símbolos. Esto puede hacerse de forma similar a C++ definiendo el atributo después de la palabra clave class. En el siguiente ejemplo se utiliza la macro MYSHAREDLIB_EXPORT, que está definida en "mysharedlib_global.h". Consulte Creación de bibliotecas compartidas para obtener más información sobre cómo funciona esto.

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

LOS ELEMENTOS PROP

Q_PROPERTY se crean utilizando la palabra clave PROP en el archivo rep. La sintaxis es la palabra clave PROP seguida de la definición entre paréntesis, donde la definición es el tipo, el nombre y (opcionalmente) un valor o atributos por defecto.

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)

Puede encontrar más información sobre la creación de tipos personalizados aquí.

Por defecto, las propiedades tendrán getters y una ranura "push" definida, así como una señal notify emitida cuando se cambia el valor. Qt Remote Objects requiere la señal notify en el objeto Source para activar el envío de actualizaciones a las Replicas adjuntas. En versiones anteriores de QtRO, las propiedades eran por defecto de lectura/escritura, es decir, tenían getters y setters. Sin embargo, debido a la naturaleza asíncrona de QtRO, esto conducía a veces a un comportamiento poco intuitivo. Establecer el atributo READWRITE en la PROP proporcionará el antiguo comportamiento (getter y 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

Si es necesario bloquear hasta que el valor es cambiado, algo como lo siguiente es necesario.

// 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 ahora utiliza por defecto READPUSH, que proporciona un slot generado automáticamente para solicitar un cambio de propiedad.

// 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)

También se pueden utilizar las palabras clave CONSTANT, READONLY, PERSISTED, READWRITE, READPUSH, o SOURCEONLYSETTER en la declaración PROP, lo que afecta a cómo se implementa la propiedad. READPUSH es el valor por defecto si no se utiliza ningún valor.

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

Tenga en cuenta que hay algunas sutilezas aquí. Una PROP CONSTANTE tiene un Q_PROPERTY declarado como CONSTANTE en el lado FUENTE. Sin embargo, las réplicas no pueden conocer el valor correcto hasta que son inicializadas, lo que significa que el valor de la propiedad tiene que poder cambiar durante la inicialización. Para READONLY, la fuente no tendrá ni un setter ni un push slot, y el lado de la réplica no tendrá un push slot generado. Si se añade el rasgo PERSISTED a una PROP, ésta utilizará la instancia QRemoteObjectAbstractPersistedStore establecida en un Nodo (si existe) para guardar/restaurar los valores de la PROP.

Otro valor matizado es SOURCEONLYSETTER, que proporciona otra forma de especificar un comportamiento asimétrico, donde la Fuente (específicamente la clase helper, SimpleSource) tendrá un getter y setter público para la propiedad, pero será ReadOnly (con una señal de notificación) en el lado de la Réplica. Por lo tanto, la propiedad puede ser totalmente controlada desde el lado de la Fuente, pero sólo observada desde el lado de la Réplica. SOURCEONLYSETTER es el modo utilizado por repc para las instancias MODEL y CLASS, lo que significa que el Origen puede cambiar el objeto apuntado, pero la Réplica no puede proporcionar un nuevo objeto, ya que no se genera ningún método set<Prop> o push<Prop>. Tenga en cuenta que esto no afecta al comportamiento de las propiedades del tipo apuntado, sólo a la capacidad de cambiar el propio puntero.

CLASE

La palabra clave CLASS genera elementos especiales Q_PROPERTY para objetos derivados de QObject. Estas propiedades tienen la misma semántica que SOURCEONLYSETTER. La sintaxis es la palabra clave CLASS seguida del nombre de la propiedad y, a continuación, el tipo de subobjeto encerrado entre paréntesis.

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

class MainClass
{
    CLASS subObject(OtherClass)
}

MODELO

La palabra clave MODEL genera elementos Q_PROPERTY especiales para objetos derivados de QAbstractItemModel. Estas propiedades tienen la misma semántica que SOURCEONLYSETTER. La sintaxis es la palabra clave MODEL seguida del nombre de la propiedad y, a continuación, paréntesis que encierran las funciones (separadas por comas) que deben exponerse a la réplica.

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

SEÑAL

Los métodos deseñal se crean utilizando la palabra clave SIGNAL en el archivo rep.

Se utiliza para declarar SIGNAL seguido de la firma deseada entre paréntesis. El valor de retorno void debe omitirse.

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

Al igual que en Qt queued connections, los parámetros de las señales que son referencias se copiarán cuando se pasen a las réplicas.

SLOT

Los métodos deranura se crean utilizando la palabra clave SLOT en el archivo rep.

El uso es declarar SLOT seguido de la firma deseada envuelta entre paréntesis. El valor de retorno puede incluirse en la declaración. Si se omite el valor de retorno, se utilizará void en los archivos generados.

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))

Al igual que en Qt queued connections y QtRO SIGNALS, los parámetros de las ranuras que son referencias se copiarán cuando se pasen a las réplicas.

ENUM

Las enumeraciones (que utilizan una combinación de enum de C++ y Q_ENUM de Qt en QtRO) se describen utilizando la palabra clave 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}

Temas relacionados: El tipo ENUM, palabra clave USE_ENUM

El tipo POD

Plain Old Data (POD) es un término para describir una simple colección de datos, en la línea de un struct de C++. Por ejemplo, si tienes una API para una agenda telefónica, puede que quieras utilizar el concepto de "dirección" en su interfaz (donde dirección podría incluir calle, ciudad, estado, país y código postal). Puede utilizar la palabra clave POD para definir objetos como este, que luego pueden ser utilizados por en las definiciones PROP/SIGNAL/SLOT en sus definiciones de clase.

Se utiliza para declarar POD seguido por el nombre del tipo generado, seguido por pares de tipo y nombre separados por comas, donde los pares tipo/nombre están entre paréntesis.

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 ejemplo completo sería el siguiente

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

El código generado por repc crea una clase Q_GADGET para cada POD, con los correspondientes miembros Q_PROPERTY para cada tipo definido para el POD.

Al utilizar los archivos de cabecera generados dentro de una biblioteca, puede ser necesario definir atributos de clase para establecer la visibilidad de los símbolos. Esto puede hacerse definiendo el atributo después de la palabra clave POD. En el siguiente ejemplo se utiliza la macro MYSHAREDLIB_EXPORT, que está definida en "mysharedlib_global.h". Consulte Creación de bibliotecas compartidas para obtener más información sobre cómo funciona esto.

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

El tipo ENUM

A menudo es más fácil y limpio definir un ENUM dentro de una clase (véase ENUM), pero si necesita un tipo enum independiente, puede ser útil utilizar la palabra clave ENUM fuera de la definición de una clase. Esto generará una nueva clase en sus ficheros de cabecera que se encargará de marshalling, etc.. La sintaxis es idéntica a ENUM, con la excepción de que la declaración en este caso no está contenida en una declaración class.

Temas relacionados: ENUM, palabra clave USE_ENUM

Palabra clave USE_ENUM

La palabra clave USE_ENUM se implementó antes de que se añadiera la autogeneración mediante la palabra clave ENUM. Se mantiene por compatibilidad con versiones anteriores.

Temas relacionados: ENUM, El tipo ENUM

Directivas

El fichero rep define una interfaz, pero las interfaces a menudo requieren elementos externos. Para soportar esto, repc incluirá cualquier directiva (de una sola línea) en la parte superior de los ficheros generados. Esto le permite, por ejemplo, utilizar directivas #include o #define que soporten la lógica o los tipos de datos necesarios.

Actualmente, la herramienta repc ignora todo lo que va desde el símbolo "#" hasta el final de línea y lo añade a los ficheros generados. Por lo tanto, las sentencias #if/#else/#endif de varias líneas y las macros de varias líneas no son compatibles.

Existen dos directivas especiales, #HEADER y #FOOTER. Estas directivas pueden utilizarse para definir contenido que debe incluirse tal cual en el código generado, ya sea antes (HEADER) o después (FOOTER) de la declaración de interfaces. Se eliminan los tokens #HEADER y #FOOTER y un carácter de espacio en blanco.

En el siguiente ejemplo, las clases repc generadas se colocan dentro de un espacio de nombres.

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

Funciones CMake

A continuación se enumeran las funciones de CMake para generar tipos fuente y réplica.

qt_add_repc_merged

Crea archivos de cabecera C++ para tipos fuente y réplica a partir de los archivos .rep de Qt Remote Objects.

qt_add_repc_replicas

Crea archivos de cabecera C++ para tipos réplica a partir de los archivos Qt Remote Objects.rep.

qt_add_repc_sources

Crea archivos de cabecera C++ para tipos fuente a partir de los archivos .rep de Qt Remote Objects.

qt_reps_from_headers

Crea archivos .rep a partir de los archivos de cabecera QObject.

variables qmake

REPC_REPLICA

Especifica los nombres de todos los archivos rep del proyecto que deben utilizarse para generar archivos de cabecera de réplica.

Por ejemplo:

REPC_REPLICA = media.rep \
               location.rep

El(los) archivo(s) generado(s) tendrá(n) la forma rep_<replica file base>_replica.h.

REPC_SOURCE

Especifica los nombres de todos los archivos rep del proyecto que deben utilizarse para generar archivos de cabecera fuente.

Por ejemplo:

REPC_SOURCE = media.rep \
              location.rep

El fichero o ficheros generados tendrán la forma rep_<replica file base>_source.h.

REPC_MERGED

Especifica los nombres de todos los archivos rep del proyecto que deben utilizarse para generar archivos de cabecera combinados (fuente y réplica).

Por ejemplo:

REPC_MERGED = media.rep \
              location.rep

Los archivos generados tendrán la forma rep_<replica file base>_merged.h.

Nota: Normalmente las fuentes y las réplicas viven en procesos o dispositivos separados, por lo que esta variable no se utiliza habitualmente.

QOBJECT_REP

Especifica los nombres de los archivos de cabecera QObject existentes que deben utilizarse para generar los archivos .rep correspondientes.

Véase también 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.