Расширение макроса в moc - PullRequest
       33

Расширение макроса в moc

5 голосов
/ 08 ноября 2010

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

#define DB_TABLE( TABLE ) \
    Q_CLASSINFO( "db_table", #TABLE )

#define DB_FIELD( PROPERTY, COLUMN ) \
    Q_CLASSINFO( "dbcol_" #PROPERTY, #COLUMN )

class Foo : public QObject
{
    Q_OBJECT
    DB_TABLE( some_table )
    DB_FIELD( clientName, client_name )
}

К сожалению, moc не расширяет макросы, поэтому Q_CLASSINFO не добавляется.

Я пыталсяfeed moc с уже обработанным исходным кодом, но он не работает на некоторых включенных классах Qt.

Знаете ли вы какой-нибудь обходной путь для этого?

Ответы [ 2 ]

11 голосов
/ 09 февраля 2013

Простой способ сделать это - модифицировать препроцессор moc.

  1. Перейти к исходному коду Qt в qtbase / src / tools / moc например (C: \ Qt \ Qt5.0.1 \ 5.0.1 \ Src \ qtbase \ src \ tools\ moc)
  2. Создайте новую копию проекта moc, например, moc_modified
  3. Откройте копию проекта moc с помощью QtCreator (файл moc.pro)
  4. Откройте файл preprocessor.cpp иперейти к Символы препроцессора :: предварительно обработанный (const QByteArray & filename, QIODevice * file) function
  5. Поиск строки:

    // phase 1: get rid of backslash-newlines
    input = cleaned(input);
    
    // <- insert your code to modify input variable
    // input is a QByteArray object that contents the source code of .h file than moc is processing
    // I had created the replaceCustomMacros function, see next line
    replaceCustomMacros(input);
    ...
    
  6. Скомпилируйте новый исходный код.Исполняемый файл moc создается в папке / bin (если вы используете windows, посмотрите на c: /bin/moc.exe)

  7. Перейдите в Qt bin (C: \ Qt \ Qt5.0.1 \ 5.0.1 \ msvc2010 \ bin) и переименуйте исполняемый файл moc, например, moc.exe.bak

  8. Скопируйте новый исполняемый файл moc в папку Qt bin.

  9. В вашем текущем приложении вам нужно создать макрос, например:

    #ifndef Q_MOC_RUN
    #define DB_FIELD( PROPERTY, COLUMN )
    #endif
    
    //or in my case
    
    #ifndef Q_MOC_RUN
    #define Q_SERVICE_INFO(method, path, type)
    #endif
    

Наконец, я предоставлю вам свой собственный исходный код функции replaceCustomMacros:

Эта функция преобразует Q_SERVICE_INFO (метод, путь, тип) макрос в Q_CLASSINFO ("srv: // метод", "тип: путь")

void Preprocessor::replaceCustomMacros(QByteArray &source)
{
    QString str(QLatin1String(source.data()));
    QString param_exp(QLatin1String("([^,\n]+)"));
    QByteArray expression("Q_SERVICE_INFO\\s*\\(");
    expression
        .append(param_exp.toLatin1())
        .append(",")
        .append(param_exp.toLatin1())
        .append("(,")
        .append(param_exp.toLatin1())
        .append(")?\\)");
    QRegExp *reg_ex = new QRegExp(QLatin1String(expression));
    int pos = -1, offset = -1, len = str.length();
    while ((offset = reg_ex->lastIndexIn(str, pos)) != -1)
    {
            reg_ex->cap(1);
            pos = -(len - offset) - 1;

            QString capturedString = reg_ex->capturedTexts().at(0);

            QString pattern = capturedString;
            pattern.remove(0, pattern.indexOf(QLatin1String("(")) + 1);
            pattern.remove(pattern.length() - 1, 1);
            QStringList params = pattern.split(QLatin1String(","));

            QString method = params.at(0).trimmed();
            method = method.mid(1, method.length() - 2);

            QString type;
            if (params.length() < 3)
            {
                type.append(QLatin1String("GET"));
            }
            else
            {
                type = params.at(2).trimmed();
                type = type.mid(1, type.length() - 2);
            }

            QString path = params.at(1).trimmed();
            path = path.mid(1, path.length() - 2);

            source.replace(offset, capturedString.length(), QString(QLatin1String("Q_CLASSINFO(\"srv://%1\",\"%2:%3\")")).arg(method, type, path).toLatin1());
    }
    delete reg_ex;

}

Я не нашел какого-либо конкретного решения в Интернете, тогда я опубликовал это решение.

Удачи:)

4 голосов
/ 08 ноября 2010

Кроме прокрутки вашего собственного препроцессора pre-moc, нет.Это то, что делает MeeGo Touch, например.Поскольку сами Nokia это делают, я считаю, что другого пути нет.

В вашем случае это будет включать только перевод ваших собственных объявлений в Q_CLASSINFO, так что это не должно быть слишком сложно.Если вы используете qmake, его также можно добавить в последовательность сборки.

...