이 페이지에서

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 파일 형식은 QtRO( Qt Remote Objects )에서 지원되는 인터페이스를 설명하기 위한 간단한 도메인 특정 언어(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 는 연결된 Replica로 업데이트를 전송하기 위해 Source 객체의 notify 신호를 필요로 합니다. 이전 버전의 QtRO에서는 속성이 기본적으로 읽기/쓰기(즉, getter와 setter를 갖는)로 설정되어 있었습니다. 그러나 QtRO의 비동기적 특성으로 인해 이로 인해 때때로 직관적이지 않은 동작이 발생하기도 했습니다. PROP에 READWRITE 속성을 설정하면 이전 방식(getter와 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

값이 변경될 때까지 블록해야 하는 경우, 다음과 같은 코드가 필요합니다.

// 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는 노드에 설정된(있는 경우) QRemoteObjectAbstractPersistedStore 인스턴스를 사용하여 PROP 값을 저장하거나 복원합니다.

또 다른 미묘한 값은 SOURCEONLYSETTER로, 비대칭적인 동작을 지정하는 또 다른 방법을 제공합니다. 이 경우 소스 (구체적으로는 헬퍼 클래스인 SimpleSource)에는 해당 속성에 대한 공개 getter와 setter가 있지만, 복제본 측에서는 읽기 전용(notify 신호 포함)으로 처리됩니다. 따라서 이 속성은 소스 측에서 완전히 제어할 수 있지만, 복제본 측에서는 관찰만 가능합니다. SOURCEONLYSETTER는 repc가 MODEL 및 CLASS 인스턴스에 사용하는 모드로, 소스(Source) 는 포인터가 가리키는 객체를 변경할 수 있지만, set<Prop> 또는 push<Prop> 메서드가 생성되지 않으므로 리플리카(Replica) 는 새로운 객체를 제공할 수 없습니다. 이는 포인터가 가리키는 타입의 속성 동작에는 영향을 미치지 않으며, 포인터 자체를 변경하는 기능에만 영향을 미친다는 점에 유의하십시오.

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

Qt XML queued connections 및 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 유형

POD(Plain Old Data)는 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는 생성된 파일의 맨 위에 (한 줄짜리) 지시문을 포함시킵니다. 이를 통해 예를 들어, 필요한 논리나 데이터형을 지원하는 #include 또는 #define 지시문을 사용할 수 있습니다.

현재 repc 도구는 “#” 기호부터 줄 끝까지의 모든 내용을 무시하고, 이를 생성된 파일에 추가합니다. 따라서 여러 줄로 구성된 #if/#else/#endif 문이나 여러 줄로 구성된 매크로는 지원되지 않습니다.

#HEADER 와 #FOOTER 라는 두 가지 특수 지시어가 있습니다. 이 지시어들은 인터페이스 선언 전(HEADER)이나 후(FOOTER)에 생성된 코드에 있는 그대로 삽입되어야 하는 내용을 정의하는 데 사용할 수 있습니다. 앞부분의 #HEADER 및 #FOOTER 토큰과 공백 한 자는 제거됩니다.

다음 예제에서는 생성된 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.