Macro expansion in moc

核能气质少年 提交于 2019-11-29 14:36:41
andref

Other than rolling your own pre-moc preprocessor, no. That is what MeeGo Touch does, for example. Since Nokia themselves are doing it, I believe there is no other way.

In your case, it would only involve translating your own declarations into Q_CLASSINFO, so it shouldn't be too hard. If you use qmake, it can be added to the build sequence, too.

Javier Baez

The easy way to make that is modifing moc preprocessor.

  1. Go to Qt source code to qtbase/src/tools/moc e.g. (C:\Qt\Qt5.0.1\5.0.1\Src\qtbase\src\tools\moc)
  2. Create a new copy of moc project e.g. moc_modified
  3. Open the copy of moc project with QtCreator (moc.pro file)
  4. Open preprocessor.cpp file and go to Symbols Preprocessor::preprocessed(const QByteArray &filename, QIODevice *file) function
  5. Search the line:

    // 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 the new source code. The moc executable file is generated to /bin folder (if you use windows look at c:/bin/moc.exe)

  7. Go to Qt bin (C:\Qt\Qt5.0.1\5.0.1\msvc2010\bin) folder and rename moc executable file e.g. moc.exe.bak

  8. Copy new moc executable file to Qt bin folder.

  9. In your current app you need to create a Macro for example:

    #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
    

Finally I let you my own source code of function replaceCustomMacros:

This function convert Q_SERVICE_INFO(method, path, type) 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;

}

I have not found any specific solution on Internet then I have posted this solution.

Good Luck :)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!