전처리 단계없이 Qt는 얼마나 유용합니까?
라이브러리가 특별한 도구로 내 소스 코드를 전처리해야하는 것은 부당하다고 생각합니다. 즉, 여러 사람들이 크로스 플랫폼 GUI 개발을 위해 Qt 라이브러리를 추천했습니다.
전처리 단계없이 Qt는 얼마나 유용합니까?
편집 : 좋아 사람들, 나는이 질문을 Qt에 대한 찢어짐으로 의미하지 않습니다. 너무 많은 Qt 팬보이가 마치 그렇게 취급하고 있습니다. Qt가이 전처리 도구를 내놓았다는 사실의 장점에 대해 논의하고 싶지 않습니다. 나는 도구가 왜 거기에 있는지 이해하고, 왜 전처리라는 아이디어를 바탕으로 만들어진 Qt 디자인의 많은 부분이 있는지 이해합니다.
나는 Qt를 사용한 적이 없다. 나는 그것을 찢을 위치에 있지 않다. 그러나 나는 전체 빌드 프로세스를 분리하는 데 의존하지 않고 소량의 상용구를 직접 작성하는 데 훨씬 더 많은 비용을 지불하고 싶습니다. 같은 이유로 현재 프로젝트에서 Flex와 Bison을 사용하지 않을 것입니다. 이러한 도구를 사용하지 않으면 다른 종류의 전처리를 사용하지 않을 것입니다.
그러니 저를 Qt에서 추출하는 것으로 받아들이지 마십시오. 나는 그것이 얼마나 좋은지에 대해 언급 할 수 없다. 나는 그것을 사용하지 않았습니다. .NET없이 사용할 수 있는지 알고 싶습니다 moc
.
Qt는 단지 그것을 사용하기 위해 moc를 사용할 필요가 없으며, QObject의 서브 클래스를 생성하고 사용자 정의 클래스에서 신호와 슬롯을 선언하는 경우 그 사용이 필요합니다.
불합리하지 않고 moc는 C ++에없는 기능, 신호 / 슬롯, 인트로 스펙 션 등을 제공합니다.
따라서 최소한의 고급 작업을 수행하려면 moc 전처리기를 사용해야합니다. 당신은 그것을 좋아하거나 싫어합니다.
Qt가 라이브러리가 얼마나 크고 포괄적인지를 고려할 때 특별한 전처리 도구가 필요한 것은 부당하다고 생각하지 않습니다.
Boost 및 GLib와 같이 유사하게 포괄적 인 다른 라이브러리에는 특별한 전처리 도구가 필요하지 않지만 표준 C 전처리기를 광범위하게 사용합니다. Qt는 C 전처리기만 사용하여 구현할 수 있지만 자체 특수 전처리 도구를 사용하면 더 깨끗한 구문을 제공하고 C 전 처리기 매크로와 관련된 많은 함정을 피할 수 있습니다.
이미 답변했듯이 신호와 슬롯이 필요한 것은 아니지만 moc없이 Qt를 사용할 수 있습니다. 예, 여기에는 모든 GUI 항목 이 포함 되지만 Qt는 단순히 GUI 라이브러리 가 아닙니다 .
나는 완전한 답을 가지고 있지는 않지만 내가 이해하기 때문에 moc는 주로 (또는 아마도 유일한) 추가 C ++ 코드를 생성합니다. 따라서 잠재적으로 수동으로 수행 할 수없는 작업은 없습니다. 그러나 그 코드에 필요한 모든 개념과 세부 사항을 이해하기 위해 얼마나 지루할 수 있는지, 얼마나 많은 연구가 필요할지 모릅니다.
또한 내 의견으로는 Qt와 moc에 대해 많은 방어를 받고있는 이유는 질문을 "불합리하다고 생각합니다"라는 강력한 단어로 시작했기 때문입니다. moc이 존재 했어야한다고 생각합니다. 이것은 실제 질문에서 산만합니다. "moc는 내 빌드 시스템에 맞지 않습니다."라고 말하거나 단순히 "사용하고 싶지 않은 이유가 있습니다."라고 말하는 것이 더 낫다고 생각합니다.
이제 완전히 사용할 수 있습니다. moc의 메인테이너는 일반 Qt보다 약간 더 장황한 구문을 가진 대안을 만들었지 만 표준 C ++ 14를 사용하므로 추가 단계가 없습니다.
(제외로, moc는 코드 생성기만큼 전처리 단계가 아닙니다. 작성한 코드는 유효한 C ++이며 moc는 어떤 것도 변경하지 않습니다. 단지 추가 C ++ 코드를 생성합니다.)
피하면서 Qt를 moc
사용하는 것은 의도 한대로 함께 사용하는 것보다 더 어려울 것입니다. 또한 다른 사람들이 Qt를 추천하도록 동기를 부여한 대부분의 흥미로운 기능을 희생 할 것입니다.
moc
당신 없이는 할 수 없습니다
- 신호 및 슬롯 사용 (모두 UI에 필요함)
- 동적 속성 시스템 사용 (특히 플러그인 작성에 필요)
- 국제화 기능 사용
- 아무것도 작동하지 않을 때 누구의 도움을받을 수 있습니다.
Qt를 사용하려면 moc
. 사실 걱정하지 말고 moc
QMake를 사용하십시오. 다음과 같은 QMake .pro 파일을 작성할 수 있습니다.
TARGET = myApp
FORMS += MainWindow.ui
HEADERS += MainWindow.h
SOURCES += MainWindow.cpp
SOURCES += main.cpp
모든 것이 자동으로 처리됩니다. 또는 피하는 방법을 알아 내기 위해 모든 시간을 할애 할 수 있습니다 moc
.
참조 https://doc.qt.io/archives/qt-4.7/metaobjects.html 및 https://doc.qt.io/archives/qt-4.7/moc.html#moc
QObjects를 사용하지 않고 Qt에서 그렇게 독특하고 유용한 것을 생각할 수 없습니다. 나는 그들이 그 사전 컴파일 단계에서 그들의 방식대로 일했으면 좋겠다.
moc없이 Qt를 사용할 수 있지만 특정 기능, 특히 처음에 Qt를 흥미롭게 만드는 기능 (대부분의 GUI 항목, 신호 및 슬롯, 문자열 번역)을 잃게됩니다. 그러나 moc가 없어도 여전히 훌륭한 범용 라이브러리입니다.
가능합니까? GUI 프로그래밍을하지 않는 한 아마도. 개인적으로 저는 요즘 주로 PyQt를 사용하므로 큰 걱정거리는 아닙니다.
신경 쓰지 않는 이유 : cmake 또는 qmake를 사용하는 경우 "미리 컴파일"의 특성을 감안할 때 불편한 점에서 큰 문제는 아닙니다. 요즘 GUI로 무언가를하고 있다면 어쨌든 대부분의 작업에 그래픽 디자이너를 사용해야하므로 이미 몇 가지 "사전 컴파일"단계를 추가하고 있습니다.
그들이 그것을 한 이유에 관하여 : 당신은 Qt의 설명을 읽는 것에 관심이있을 것이다 : http://doc.qt.io/qt-4.8/templates.html
요약하면 다음과 같습니다.
- 템플릿 솔루션에는 속성과 오버로딩이 없습니다.
- moc 솔루션은 신호가 바이너리 호환성을 깨는 것을 방지합니다.
- 템플릿이없는 신호 / 슬롯 메커니즘으로 런타임 분석 및 수정 가능
참고로, 멀티 스레딩 신호 / 슬롯도 시스템의 장점입니다.
저는 현재 MOC에 대한 대안을 찾아야하는 위치에 있습니다. 지금까지 텍스트 번역에 GLib를 사용하고 C ++ 템플릿과 C 매크로를 결합하여 웹 (시그 슬롯)에서 찾은 신호 / 슬롯 라이브러리를 리엔지니어링하는 중입니다. 지루하고 지루한 부분은 내 앱의 GUI를 다시 실행하고 위젯 프로모션 (Qt Designer의 기능)을 통해 일반 Qt 위젯을 내 위젯 (예 : QPushButton-> MyPushButton)으로 대체하는 것입니다. 이런 식으로 위젯이 Qt 대신 템플릿 신호를 방출하도록 할 수 있습니다. 캐치가 있습니다. 내 "수정 된"위젯 클래스는 전처리기를 통해 실행되어야하지만 이는 일생에 한 번의 단계입니다. 그 다음으로 넘어갈 수 있습니다.
자체 이벤트 루프 (Qt의 이벤트 루프 코드에 피기 백하는 래퍼), 멀티 스레딩 및 문자열 클래스 등이있는 Application Framework 라이브러리를 이미 작성했기 때문에이 모든 작업을 수행 할 여유가 있습니다. 내 프로젝트에는 멋지고 멋진 위젯을 표시하는 Qt.
그러나 이러한 도구를 마음대로 사용할 수 없다면-저를 믿으십시오. Qt의 전처리기를 제거하는 것은 엄청난 고통이 될 것입니다.
여러분 께 드리는 메시지는 다음과 같습니다. QMake 또는 moc를 사용할 수 있으면 사용하십시오.
Qt 개체에서 오는 신호에만 연결해야하는 경우 해킹 솔루션은 연결하려는 신호의 서명과 일치하는 공개 또는 보호 된 가상 슬롯이있는 기존 QT 개체를 활용하는 것입니다. QT 객체를 서브 클래 싱하고 가상 슬롯을 프록시로 다시 구현하여 QT 신호가 방출 될 때 필요한 모든 작업을 수행 할 수 있습니다. 예 :
class SignalProxy : public QWidget
{
public:
SignalProxy() {}
void setVisible( bool isVisible )
{
// Do whatever you want to do when the signal is emitted.
}
};
// code to connect the signal, e.g., to a QWebView object
SignalProxy proxy;
QWebView webview;
QObject::connect( &webview, SIGNAL(loadFinished(bool)),
&proxy, SLOT(setVisible(bool)) );
예쁘지는 않지만 작업이 완료됩니다. MOC없이 작업하려는 경우 기존 Qt 개체를 찾아 필요한 신호 서명에 대한 프록시로 사용할 수 있습니다. 예를 들어 QAbstract ... 클래스에는 많은 가상 슬롯이 있으며 모든 것을 숨길 수 있습니다. QT 신호에 연결하기위한 부스트 신호 또는 tr1 :: function <> 스타일 API를 제공하는 라이브러리의 불쾌 함.
일반적으로 slot 메소드를 직접 호출 할 수 있으므로 QT 객체에서 슬롯을 호출하는 것은 신호를 수신하는 것보다 덜 중요합니다.
나는 매우 깨끗하지 않고 100 % 만족스럽지 않은 솔루션을 가지고 있지만 MOC 컴파일러를 사용하지 않고도 Qt 신호를 자신의 코드에 연결할 수 있습니다 (질문에서와 똑같은 제약 조건이 있습니다. 내 응용 프로그램의 빌드 프로세스에서 MOC 컴파일러를 실행하려면).
MOC를 사용하지 않고 Qt 신호를 캡처 할 수 있도록 다음 트릭을 사용하고 있습니다.
(1) QMetaCallEvent 정의 가져 오기 (에서 복사) : Qt 5.x에서는 다음과 같은 내용을 갖게됩니다.
class QMetaCallEvent : public QEvent {
public:
inline int id() const {
return method_offset_ + method_relative_;
}
virtual void placeMetaCall(QObject *object);
private:
QMetaCallEvent();
void* slotObj_;
const QObject *sender_;
int signalId_;
int nargs_;
int *types_;
void **args_;
void *semaphore_;
void *callFunction_;
ushort method_offset_;
ushort method_relative_;
};
(2) Qt 신호를 캡처해야하는 위젯 클래스에서 Qt 위젯 (예 : QButton)에서 상속하고 다음 함수를 정의합니다.
// Inspired by QObject::connect() in src/corelib/kernel/qobject.cpp
bool connect_sender(
const QObject* sender, const char* signal, int method_index
) {
// We need to generate MetaCall events (since QObject::event()
// is the only virtual function we can overload)
// (note that the other connection types do not generate events).
Qt::ConnectionType type = Qt::QueuedConnection ;
if(sender == 0 || signal == 0) {
std::cerr << "null sender or signal" << std::endl ;
return false ;
}
QByteArray tmp_signal_name;
const QMetaObject *smeta = sender->metaObject();
++signal; //skip code
int signal_index = smeta->indexOfSignal(signal);
if (signal_index < 0) {
// check for normalized signatures
tmp_signal_name =
QMetaObject::normalizedSignature(signal).prepend(*(signal - 1));
signal = tmp_signal_name.constData() + 1;
signal_index = smeta->indexOfSignal(signal);
if (signal_index < 0) {
std::cerr << "Signal \'" << signal << "\' not found"
<< std::endl ;
return false;
}
}
int *types = 0;
QMetaObject::connect(
sender, signal_index, this, method_index, type, types
) ;
return true ;
}
(3) event () 함수 오버로드 :
bool event(QEvent* e) {
if(e->type() == QEvent::MetaCall) {
QMetaCallEvent* ev = static_cast<QMetaCallEvent*>(e);
switch(ev->id()) {
// insert your handling code here
}
return true;
}
return QObject::event(e) ;
}
Now, if you call connect_sender(qobject, signal_name, method_index), this will call event() each time the signal is fired, with the specified method_index retrieved in ev->id().
Important note: I have been using this trick in my application for several years, it works quite well, but it is not very clean. One of the consequences is that whenever the definition of QMetaCallEvent changes, you need to edit your declaration accordingly (unfortunately it is not exposed in the header files of Qt).
(sorry for reviving such an old post)
I was required to do a C/W assignment for my MSc unit in 3D Software Development.
Unfortunately a requirement was to use Qt to provide an OpenGL context rather than use Glut, native X11, Gtk etc...
I did not want to use MOC and with a lot of fiddling I was able to get just enough callbacks (such as keyboard, mouse, paint, timer etc...) to make a usable submission. So for using Qt with a primary reason for OpenGL software, it actually works fine without MOC.
However, I can't see how a full application could be developed without using MOC. Which is a shame.
This Qt MOC thing is a pain. I don't understand why so many C++ developers seem to find it acceptable frankly. It is extremely unportable and will get crusty fast! (Just try to get some Borland Kylix C++ code to compile. You will soon realize what a bad idea this is).
If I wanted to use non-standard C++, I would just use Microsoft C++/CLI.
참고URL : https://stackoverflow.com/questions/3588154/how-usable-is-qt-without-its-preprocessing-step
'developer tip' 카테고리의 다른 글
Chrome 인증서 / HSTS 오류를 우회하기 위해 'badidea'또는 'thisisunsafe'를 사용하는 것은 현재 사이트에만 적용 되나요? (0) | 2020.12.13 |
---|---|
.NET 4.0의 주요 변경 사항 (0) | 2020.12.13 |
정말, Git에서 병합하는 것이 SVN보다 쉬운 구체적인 예? (0) | 2020.12.13 |
정의되지 않은 전달의 목적은 무엇입니까? (0) | 2020.12.12 |
자바 스크립트 : 배경 이미지 URL 가져 오기 (0) | 2020.12.12 |