2010-11-07 5 views
4

Я хотел бы сохранить некоторую информацию о классе с помощью макроса Q_CLASSINFO. Тем не менее, я хотел бы, чтобы обернуть его в моей собственной макрокоманды, например:Расширение макроса в moc

#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 не добавляется.

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

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

+0

Для записи: Mt Qt 5 расширяет макросы. – peppe

ответ

4

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

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

+0

Мои макросы содержат больше Q_CLASSINFO, я упростил их для ясности. Прямо сейчас, кажется, много неприятностей для небольшого выигрыша, поэтому я поставлю Q_CLASSINFO непосредственно в код. Спасибо за ваш ответ. – zarzych

11

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

  1. Перейти к Qt исходный код qtbase/SRC/инструменты/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 & имя файла, QIODevice файл *) функция
  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. Compile новый исходный код. Исполняемый файл moc создается в папке/bin (если вы используете окна, смотрите 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 (метод, путь, тип) macro to Q_CLASSINFO ("srv: // method", "type: path")

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

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

Удачи :)

Смежные вопросы