このページでは

Qt Remote Objects コンパイラ

REPCの概要

Replica コンパイラ(repc) は、API 定義ファイルに基づいてQObject ヘッダーファイルを生成します。 このファイル(「rep」ファイルと呼ばれる)は、特定の(テキスト)構文を使用して API を記述します。慣例により、これらのファイルには Replica の略称である .rep というファイル拡張子が付けられます。repc によってこれらのファイルが処理されると、repcはソースヘッダーファイルと Replicaヘッダーファイルの両方を生成します。

Qt Remote Objects モジュールには、プロジェクトファイルに追加することでrepcを自動的に実行し、生成されたファイルをビルドプロセス中にMeta-Object Compilerによって処理されるファイルのリストに追加できるCMake関数や qmake変数も含まれており、プロジェクトでのQt Remote Objects の利用を容易にします。

Qt Remote Objects は、ネットワークを介して任意のQObject を共有することをサポートしていますが(ソース側ではenableRemoting、レプリカ側ではacquireDynamicを使用)、repcにオブジェクトの定義を任せることにはいくつかの利点があります。まず第一に、DynamicReplicas は便利ですが、扱うにはやや面倒です。 オブジェクトが初期化されるまでAPIが判明せず、C++からAPIを使用するには、QMetaObject のメソッドを介して文字列検索を行う必要があります。第二に、コンパイル時にインターフェースが判明していれば、実行時ではなくコンパイル時に問題を検出できます。 第三に、rep フォーマットはデフォルト値をサポートしており、レプリカがインスタンス化される際にソースが利用可能であることを保証できない場合に便利です。

生成されたファイルをコードで使用する方法については、こちらのドキュメントを参照してください。ここでは、repc 形式とオプションに焦点を当てます。

repファイル形式

rep ファイル形式は、Qt Remote Objects (QtRO)でサポートされるインターフェースを記述するためのシンプルなドメイン固有言語(DSL)です。QtRO はオブジェクトベースのシステムであるため、これらのインターフェースは、オブジェクト、つまりプロパティ、シグナル、スロットを持つクラスを通じて利用可能な API によって定義されます。

コメント

C++ スタイルの単一行コメント(// text )および C スタイルの複数行コメント(/* text * / )がサポートされています。

クラス型

rep ファイルで定義された各クラスは、生成されたヘッダーファイル内で `QObject ` となり、記述された API が自動的に生成されます。

クラスを定義するには、class キーワードの後に、その型に付けたい名前を指定し、API を次のように角括弧で囲みます。

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

ライブラリ内で生成されたヘッダーファイルを使用する場合、シンボルの可視性を設定するためにクラス属性を定義する必要があるかもしれません。これは、C++と同様に、class キーワードの後に属性を定義することで行うことができます。以下の例では、"mysharedlib_global.h" で定義されているMYSHAREDLIB_EXPORT マクロが使用されています。これがどのように機能するかについての詳細は、「共有ライブラリの作成」を参照してください。

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

PROP

Q_PROPERTY 要素は、rep ファイル内で PROP キーワードを使用して作成されます。構文は、PROP キーワードの後に括弧で囲まれた定義が続く形式です。定義には、型、名前、および(オプションで)デフォルト値や属性が含まれます。

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)

カスタム型の作成に関する詳細はこちらを参照してください。

デフォルトでは、プロパティにはゲッターと「push」スロットが定義されるほか、値が変更された際に「notify」シグナルが発信されます。Qt Remote Objects では、接続されたレプリカへの更新の送信をトリガーするために、Sourceオブジェクト上のnotifyシグナルが必要です。 以前のバージョンの QtRO では、プロパティはデフォルトで読み書き可能(つまり、ゲッターとセッターを持つ)になっていました。しかし、QtRO の非同期的な性質により、これが時に直感に反する動作を引き起こす原因となっていました。PROP に READWRITE 属性を設定することで、従来の(ゲッターとセッターを持つ)動作を実現できます。

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

値が変更されるまでブロックする必要がある場合は、次のような処理が必要になります。

// 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では現在、デフォルトでREADPUSHが設定されており、プロパティの変更を要求するためのスロットが自動的に生成されます。

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

また、PROP宣言でCONSTANT 、READONLY 、PERSISTED 、READWRITE 、READPUSH 、またはSOURCEONLYSETTER キーワードを使用することもでき、これらはプロパティの実装方法に影響を与えます。値が指定されていない場合、デフォルト値はREADPUSHとなります。

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

ここにはいくつかの微妙な点があることに注意してください。CONSTANT PROP には、SOURCE 側で CONSTANT として宣言されたQ_PROPERTY があります。しかし、レプリカは初期化されるまで正しい値を知ることができないため、初期化中はプロパティ値が変更されることを許容する必要があります。 READONLYの場合、ソース側にはセッターもプッシュスロットも存在せず、レプリカ側にもプッシュスロットは生成されません。PROPにPERSISTEDトレイトを追加すると、PROPはNodeに設定されたQRemoteObjectAbstractPersistedStore インスタンス(存在する場合)を使用して、PROPの値を保存・復元するようになります。

もう 1 つの微妙な違いを持つ値として SOURCEONLYSETTER があります。これは非対称な挙動を指定する別の方法を提供するもので、ソース側(具体的にはヘルパークラスSimpleSource )にはプロパティ用のパブリックなゲッターとセッターがありますが、レプリカ側では ReadOnly(notify シグナル付き)となります。 したがって、このプロパティはソース側から完全に制御できますが、レプリカ側からは観察のみが可能です。 SOURCEONLYSETTER は、repc が MODEL および CLASS インスタンスに対して使用するモードです。つまり、ソースはポインタ先のオブジェクトを変更できますが、set<Prop> や push<Prop> メソッドが生成されないため、レプリカは新しいオブジェクトを提供することはできません。 なお、これはポインタ先の型のプロパティの挙動には影響せず、ポインタ自体を変更する機能にのみ影響します。

CLASS

CLASSキーワードは、QObject から派生したオブジェクトに対して、特別なQ_PROPERTY 要素を生成します。これらのプロパティは、SOURCEONLYSETTERと同じ意味を持ちます。構文は、CLASS キーワードの後にプロパティ名、そして括弧で囲まれたサブオブジェクトの型が続きます。

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

class MainClass
{
    CLASS subObject(OtherClass)
}

MODEL

MODELキーワードは、QAbstractItemModel から派生したオブジェクトに対して、特別なQ_PROPERTY 要素を生成します。これらのプロパティは、SOURCEONLYSETTERと同じ意味論を持ちます。構文は、MODEL キーワード、その後にプロパティ名、さらにレプリカに対して公開すべき(コンマ区切りの)ロールを括弧で囲んだものです。

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

SIGNAL

シグナルメソッドは、repファイル内でSIGNALキーワードを使用して作成されます。

使用方法は、SIGNAL を宣言し、その後に括弧で囲んだ目的のシグネチャを記述します。void の戻り値は省略してください。

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

Qt XML のqueued connections と同様に、シグナル内の参照型パラメータは、レプリカに渡される際にコピーされます。

SLOT

スロットメソッドは、rep ファイル内で SLOT キーワードを使用して作成します。

使用方法は、SLOT を宣言し、その後に括弧で囲んだ目的のシグネチャを記述します。戻り値は宣言に含めることができます。戻り値を省略した場合、生成されたファイルでは void が使用されます。

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 Qt XML や QtRO SIGNALS と同様に、スロット内の参照型のパラメータは、レプリカに渡される際にコピーされます。

ENUM

列挙型(C++のenumとQtROのQ_ENUM を組み合わせて使用)は、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}

関連トピック:ENUM 型、USE_ENUM キーワード

POD 型

Plain Old Data (POD) は、C++ の struct に似た、単純なデータ集合を表す用語です。 たとえば、電話帳用の API がある場合、そのインターフェースで「住所」という概念を使用したいと思うかもしれません(この「住所」には、通り、都市、州、国、郵便番号などが含まれる場合があります)。 POD キーワードを使用すると、このようなオブジェクトを定義でき、クラス定義内の PROP/SIGNAL/SLOT 定義で使用することができます。

使用方法は、POD と宣言し、その後に生成される型の名前、さらにカンマで区切られた型と名のペアを記述します。型と名のペアは括弧で囲みます。

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)

完全な例は次のようになります。

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

repc によって生成されるコードは、POD ごとにQ_GADGET クラスを作成し、その POD で定義された各型に対応するQ_PROPERTY メンバーを生成します。

ライブラリ内で生成されたヘッダーファイルを使用する場合、シンボルの可視性を設定するためにクラス属性を定義する必要がある場合があります。これは、POD キーワードの後に属性を定義することで行えます。以下の例では、"mysharedlib_global.h" で定義されているMYSHAREDLIB_EXPORT マクロが使用されています。この仕組みの詳細については、「共有ライブラリの作成」を参照してください。

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

ENUM型

クラス内で ENUM を定義する方が、多くの場合、より簡単でコードもすっきりします(ENUM を参照)。しかし、独立した enum 型が必要な場合は、クラス定義の外で ENUM キーワードを使用すると便利です。これにより、ヘッダーファイル内に、マーシャリングなどを処理する新しいクラスが生成されます。 構文はENUMと同じですが、この場合はclass 宣言内に宣言が含まれない点が異なります。

関連トピック:ENUM、USE_ENUMキーワード

USE_ENUMキーワード

USE_ENUMキーワードは、ENUMキーワードによる自動生成機能が追加される前に実装されました。下位互換性を確保するために維持されています。

関連トピック:ENUM、ENUM型

ディレクティブ

repファイルはインターフェースを定義しますが、インターフェースには外部要素が必要になることがよくあります。これをサポートするため、repcは生成されたファイルの先頭に(1行の)ディレクティブをすべて含めます。これにより、例えば、必要なロジックやデータ型をサポートする#includeや#defineディレクティブを使用できるようになります。

現在、repc ツールは「#」記号から行末までのすべてを無視し、生成されたファイルにその内容を追加します。そのため、複数行にわたる #if/#else/#endif ステートメントや複数行のマクロはサポートされていません。

#HEADER と#FOOTER という2つの特別なディレクティブがあります。これらのディレクティブを使用すると、インターフェース宣言の前(HEADER)または後(FOOTER)に、生成されたコードにそのまま挿入されるべき内容を定義できます。先頭の#HEADER および#FOOTER というトークンと、それに続く1文字の空白文字は削除されます。

次の例では、生成された repc クラスが名前空間内に配置されています。

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

CMake 関数

ソース型およびレプリカ型を生成するための CMake 関数を以下に示します。

qt_add_repc_merged

Qt Remote Objects の.repファイルから、ソース型およびレプリカ型用のC++ヘッダーファイルを作成します。

qt_add_repc_replicas

Qt Remote Objects の.repファイルから、レプリカ型用のC++ヘッダーファイルを作成します。

qt_add_repc_sources

Qt Remote Objects の .rep ファイルから、ソース型用の C++ ヘッダーファイルを作成します。

qt_reps_from_headers

QObject ヘッダーファイルから .rep ファイルを作成します。

qmake 変数

REPC_REPLICA

プロジェクト内の、レプリカヘッダーファイルの生成に使用すべきすべての .rep ファイルの名前を指定します。

例:

REPC_REPLICA = media.rep \
               location.rep

生成されるファイルは、rep_<replica file base>_replica.h という形式になります。

REPC_SOURCE

プロジェクト内の、ソースヘッダーファイルの生成に使用するすべてのrepファイルの名前を指定します。

例:

REPC_SOURCE = media.rep \
              location.rep

生成されるファイルは、rep_<replica file base>_source.h という形式になります。

REPC_MERGED

プロジェクト内の、結合済み(ソースおよびレプリカ)ヘッダーファイルの生成に使用するすべての rep ファイルの名前を指定します。

例:

REPC_MERGED = media.rep \
              location.rep

生成されるファイルは、rep_<replica file base>_merged.h という形式になります。

注:通常 、ソースとレプリカは別々のプロセスまたはデバイスに存在するため、この変数は一般的に使用されません。

QOBJECT_REP

対応する .rep ファイルの生成に使用する、既存のQObject ヘッダーファイルの名前を指定します。

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.