Macro extension in moc

I would like to save some class information using the Q_CLASSINFO macro. However, I would like to wrap it in my own macro, for example:

#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 ) } 

Unfortunately, moc does not extend macros, so Q_CLASSINFO is not added.

I tried passing moc to an already preprocessed source, but it is not suitable for some of the included Qt classes.

Do you know about this workaround?

+4
source share
2 answers

Other than scrolling your own pre-moc preprocessor, no. This is what MeeGo Touch does, for example. Since Nokia does it myself, I believe that there is no other way.

In your case, this will only translate your own ads into Q_CLASSINFO, so it should not be too complicated. If you use qmake, you can also add it to the build sequence.

+4
source

An easy way to do this is to modify the moc preprocessor.

  • Go to the Qt source code in qtbase / src / tools / moc , for example. (C: \ Qt \ Qt5.0.1 \ 5.0.1 \ Src \ qtbase \ SRC \ tools \ MOC)
  • Create a new copy of the moc project, for example. moc_modified
  • Open a copy of the moc project with QtCreator (moc.pro file)
  • Open the preprocessor.cpp file and go to Symbols Preprocessor :: preprocessed (const QByteArray & filename, QIODevice * file) .
  • Find 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); ... 
  • Compile the new source code. The moc executable is created in the / bin folder (if you use windows, see c: /bin/moc.exe)

  • Go to the Qt bin folder (C: \ Qt \ Qt5.0.1 \ 5.0.1 \ msvc2010 \ bin) and rename the moc executable, for example. moc.exe.bak

  • Copy the new moc executable to the Qt bin folder.

  • In your current application, 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 give you my own source code for the replaceCustomMacros function:

This function converts the macro Q_SERVICE_INFO (method, path, type) 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 did not find any specific solution on the Internet, then I published this solution.

Good luck :)

+11
source

All Articles