Насколько пригоден Qt без шага предварительной обработки? - PullRequest
58 голосов
/ 28 августа 2010

Я думаю, что для библиотеки нецелесообразно требовать предварительной обработки моего исходного кода специальным инструментом.Тем не менее, несколько человек рекомендовали мне библиотеку Qt для разработки кроссплатформенного графического интерфейса.

Насколько пригоден Qt без шага предварительной обработки?

РЕДАКТИРОВАТЬ: Ладно, я не это имею в видувопрос как разорванный на Qt - слишком много фанатов Qt рассматривают это как если бы это было так.Я не хочу обсуждать достоинства того факта, что Qt придумала этот инструмент предварительной обработки.Я понимаю, почему этот инструмент есть, и я понимаю, почему существуют большие части дизайна Qt, которые основаны на идее предварительной обработки.

Я никогда не использовал Qt, поэтому я не в состоянии разобратьЭто.Но я бы предпочел заплатить в письменном виде небольшую часть шаблона самостоятельно и не зависеть от разрыва всего процесса сборки.Я не буду использовать Flex и Bison в моем текущем проекте по той же причине;если я не буду использовать эти инструменты, я определенно не собираюсь использовать другой вид предварительной обработки.

Так что, пожалуйста, не воспринимайте меня как копирование на Qt.Я не могу комментировать, насколько это хорошо или нет;Я не использовал это.Я просто хочу знать, возможно ли использовать его без moc.

Ответы [ 12 ]

0 голосов
/ 21 ноября 2015

У меня есть решение, которое не является сверхчистым и не на 100% удовлетворительным, но позволяет подключать сигналы Qt к вашему собственному коду без использования компилятора MOC (у меня было точно такое же ограничение, как в вопросе, т.е. не в состоянии запустить компилятор MOC в процессе сборки моего приложения).

Чтобы иметь возможность захватывать сигналы Qt без использования MOC, я использую следующие приемы:

(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) ;
}

Теперь, если вы вызываете connect_sender (qobject, signal_name, method_index), это будет вызывать event () каждый раз, когда сигнал срабатывает, с указанным указанным method_index, полученным в ev-> id ().

Важное примечание: Я использовал этот трюк в своем приложении в течение нескольких лет, он работает довольно хорошо, но он не очень чистый. Одним из последствий этого является то, что всякий раз, когда изменяется определение QMetaCallEvent, вам необходимо соответствующим образом редактировать свое объявление (к сожалению, оно не отображается в заголовочных файлах Qt).

0 голосов
/ 20 сентября 2012

(извините за возрождение такого старого поста)

Мне нужно было выполнить задание C / W для моего MSc-подразделения в разработке программного обеспечения для 3D.

К сожалению, требовалось использовать Qtчтобы обеспечить контекст OpenGL, а не использовать Glut, родной X11, Gtk и т. д ...

Я не хотел использовать MOC, и с большим трудом я смог получить достаточно обратных вызовов (таких как клавиатура,мышь, краска, таймер и т. д.), чтобы сделать полезное представление.Так что для использования Qt с основной причиной для программного обеспечения OpenGL, оно на самом деле прекрасно работает без MOC.

Однако я не могу понять, как можно было бы разработать полноценное приложение без использования MOC.Какой позор.

Эта вещь в Qt MOC - боль.Я не понимаю, почему так много разработчиков C ++, по-видимому, считают это приемлемым.Это чрезвычайно непереносимо и быстро станет хрустящим!(Просто попробуйте получить код Borland Kylix C ++ для компиляции. Вы скоро поймете, что это за плохая идея).

Если бы я хотел использовать нестандартный C ++, я бы просто использовал Microsoft C ++ / CLI.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...