문제

이 질문은 이미이 포럼에서 묻지 만 개념을 이해하지 못합니다.

나는 주위를 읽고 있었고 신호와 슬롯이 함수 포인터를 사용하여 구현되는 것 같습니다. 즉, 신호는 모든 연결된 슬롯 (함수 포인터)이라고하는 큰 기능입니다. 이 올바른지? 그리고 전체 이야기에서 생성 된 MOC 파일의 역할은 무엇입니까? 신호 기능이 어떤 슬롯을 호출 할 슬롯 이이 신호에 연결되어 있는지 이해하지 못합니다.

시간 내 줘서 고마워

도움이 되었습니까?

해결책

QT는 해석 된 언어와 비슷한 방식으로 이러한 것들을 구현합니다. 즉, 신호 이름을 함수 포인터로 맵핑하고 유지 관리하고 필요에 따라 함수 이름별로 기능 포인터를 찾는 기호 테이블을 구성합니다.

신호를 방출 할 때마다, 즉 쓴다

emit something();

당신은 실제로 전화합니다 something() Meta Object Compiler에 의해 자동으로 생성되고 *.moc 파일. 이 기능 내 에서이 신호는 현재 어떤 슬롯에 연결되어 있는지 확인하고, 자체 소스에서 구현 한 적절한 슬롯 기능 (위에서 설명한 방식)을 통해 순차적으로 호출됩니다. 그리고 emit, 다른 QT 특이 적 키워드와 마찬가지로 C ++ Preprocessor에 의해 폐기됩니다. *.moc 생성되었습니다. 실제로, QT 헤더 중 하나에서 (qobjectdefs.h), 그러한 선이 있습니다.

#define slots 
#define signals protected
#define emit

연결 함수 (connect) 내부에서 유지되는 기호 테이블 만 수정합니다 *.moc 파일과 인수가 전달되었습니다 ( SIGNAL() `슬롯 매크로)도 테이블과 일치하도록 전처리됩니다.

그것이 일반적인 아이디어입니다. 다른 대답에서 ジョージ 우리에게 링크를 제공합니다 트롤 테크 메일 링리스트에 그리고 또 다른 질문입니다 이 주제에 대해.

다른 팁

다음을 추가해야한다고 생각합니다.

거기 있습니다 또 다른 연결된 질문 - 그리고 거기 있습니다 아주 좋은 기사 그것은 그것에 대한 매우 상세한 확장으로 간주 될 수 있습니다. 대답; 이 기사는 다음과 같습니다, 개선 된 (아직 완벽하지는 않지만) 코드 구문 강조 표시.

여기에 대한 짧은 이야기가 있습니다. 실수가 발생하기 쉬운 일입니다)

기본적으로 우리가 삽입 할 때 Q_OBJECT 매크로 클래스 정의에서 사전 처리기는 정적으로 확장합니다. QMetaObject 인스턴스 선언, 동일한 클래스의 모든 인스턴스에서 공유하는 인스턴스 선언 :

class ClassName : public QObject // our class definition
{
    static const QMetaObject staticMetaObject; // <--= Q_OBJECT results to this

    // ... signal and slots definitions, other stuff ...

}

이 예는 결국 ON 초기화가 서명 ("methodname(argtype1,argtype2)")) 신호와 슬롯의 indexOfMethod() Call, Well, Method 's Index가 Signature String을 반환합니다.

struct Q_CORE_EXPORT QMetaObject
{    
    // ... skip ...
    int indexOfMethod(const char *method) const;
    // ... skip ...
    static void activate(QObject *sender, int signal_index, void **argv);
    // ... skip ...
    struct { // private data
        const QMetaObject *superdata; // links to the parent class, I guess
        const char *stringdata; // basically, "string1\0string2\0..." that contains signatures and other names 
        const uint *data; // the indices for the strings in stringdata and other stuff (e.g. flags)
        // skip
    } d;
};

이제 moc creates the moc_headername.cpp QT 클래스 헤더 파일 headername.h, 그것은 서명 문자열 및 기타 데이터를 올바르게 초기화하는 데 필요한 기타 데이터를 제공합니다. d 구조, 다음 초기화 코드를 작성합니다. staticMetaObject 이 데이터를 사용하는 싱글 톤.

그것이하는 또 다른 중요한 일은 객체의 코드 생성입니다. qt_metacall() 메소드, 객체의 메소드 ID와 인수 배열을 가져 와서 Long을 통해 메소드를 호출합니다. switch 이와 같이:

int ClassName::qt_metacall(..., int _id, void **_args)
{
    // ... skip ...
    switch (_id) {
        case 0: signalOrSlotMethod1(_args[1], _args[2]); break; // for a method with two args
        case 1: signalOrSlotMethod2(_args[1]); break; // for a method with a single argument
        // ... etc ...
    }
    // ... skip ...
}

마지막으로, 모든 신호에 대해 moc a를 포함하는 구현을 생성합니다 QMetaObject::activate() 전화 :

void ClassName::signalName(argtype1 arg1, argtype2 arg2, /* ... */)
{
    void *_args[] = { 0, // this entry stands for the return value
                      &arg1, // actually, there's a (void*) type conversion
                      &arg2, // in the C++ style
                      // ...
                    };
    QMetaObject::activate( this, 
                           &staticMetaObject, 
                           0, /* this is the signal index in the qt_metacall() map, I suppose */ 
                           _args
                         );
}

마지막으로, connect() Call은 문자열 메소드 서명을 정수 ID (사용한 것)로 변환합니다. qt_metacall()) 및 신호 대 슬롯 연결 목록을 유지합니다. 신호가 방출되면 activate() 코드는이 목록을 거쳐 그들의 qt_metacall() 방법.

요약하면, 정적 QMetaObject 인스턴스는 "메타 정보"(메소드 서명 문자열 등)를 저장합니다. qt_metacall() 메소드는 모든 신호/슬롯, 인덱스, 신호 구현으로 호출 할 수있는 "메소드 테이블"을 제공합니다. moc 이 색인을 통해 사용하십시오 activate(), 그리고 마지막으로 connect() 신호 대 슬롯 인덱스 맵 목록을 유지 관리하는 작업이 있습니까?

*참고 : 다른 스레드 사이에 신호를 전달하려는 경우이 체계의 합병증이 있습니다 (나는 하나가 blocking_activate() 코드), 그러나 일반적인 아이디어가 동일하게 유지되기를 바랍니다)

이것은 링크 된 기사에 대한 나의 대략적인 이해이므로 쉽게 잘못 될 수 있으므로 직접 읽고 읽는 것이 좋습니다).

추신. QT 구현에 대한 이해를 향상시키고 싶으므로, 내 이야기의 불일치에 대해 알려주십시오!


내 다른 (이전) 답변이 일부 열성적 인 편집자에 의해 삭제되었으므로 여기에 텍스트를 추가하겠습니다 (나는 몇 가지 세부 사항이 없습니다. ~ 아니다 Pavel Shved의 게시물에 통합되었고, 답을 삭제 한 사람이 의심 스럽다. )

@pavel shved :

QT 헤더 어딘가에 라인이 있다고 확신합니다.

#define emit

확인하기 위해 : Google 코드 검색을 통해 이전 QT 코드에서 찾았습니다. 여전히 거기에있을 가능성이 높습니다); 발견 된 위치 경로는 다음과 같습니다.

ftp://ftp.slackware-brasil.com.br›Slackware-7.1›Contrib›KDE-1.90›QT-2.1.1.TGZ›USR›LIB›QT-2.1.1›SRC›Kernel›qobjectdefs.h


다른 보완 링크 : http://lists.trolltech.com/qt-interest/2007-05/thread00691-0.html - Andreas Pakulat의 답변을 참조하십시오


그리고 여기에 또 다른 답변이 있습니다. QT 질문 : 신호와 슬롯은 어떻게 작동합니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top