후드에서 신호와 슬롯이 어떻게 구현됩니까?
-
05-07-2019 - |
문제
이 질문은 이미이 포럼에서 묻지 만 개념을 이해하지 못합니다.
나는 주위를 읽고 있었고 신호와 슬롯이 함수 포인터를 사용하여 구현되는 것 같습니다. 즉, 신호는 모든 연결된 슬롯 (함수 포인터)이라고하는 큰 기능입니다. 이 올바른지? 그리고 전체 이야기에서 생성 된 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 질문 : 신호와 슬롯은 어떻게 작동합니까?