2010-11-07 27 views
4

Je voudrais stocker des informations de classe en utilisant la macro Q_CLASSINFO. Cependant, je voudrais envelopper dans ma propre macro, par exemple:Macro expansion dans 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) 
} 

Malheureusement, moc ne se développe pas des macros de sorte que le Q_CLASSINFO n'est pas ajouté.

J'ai essayé de nourrir moc avec une source déjà prétraité, mais elle échoue sur certaines classes Qt incluses.

Savez-vous une solution de contournement pour cela?

+0

Pour l'enregistrement: Le moc de Qt 5 étend les macros. – peppe

Répondre

4

Autre que de rouler votre propre pré-processeur pré-moc, non. C'est ce que fait MeeGo Touch, par exemple. Puisque Nokia le fait lui-même, je crois qu'il n'y a pas d'autre moyen.

Dans votre cas, cela impliquerait seulement de traduire vos propres déclarations dans Q_CLASSINFO, donc cela ne devrait pas être trop dur. Si vous utilisez qmake, il peut aussi être ajouté à la séquence de construction.

+0

Mes macros contiennent plus de Q_CLASSINFO, je les ai simplifiées pour plus de clarté. En ce moment, il semble que beaucoup de problèmes pour un petit gain, donc je vais mettre Q_CLASSINFO directement dans le code. Merci pour votre réponse. – zarzych

11

Le moyen le plus simple de faire cela est de modifier le préprocesseur moc.

  1. Aller au code source Qt à qtbase/src/tools/moc par exemple (C: \ Qt \ Qt5.0.1 \ 5.0.1 \ Src \ qtbase \ src \ tools \ moc)
  2. Créer une nouvelle copie du projet moc, par ex. moc_modified
  3. Ouvrez la copie du projet moc avec QtCreator (fichier moc.pro)
  4. de fichier ouvert et preprocessor.cpp aller à symboles préprocesseur :: prétraité (const QByteArray & nom de fichier, QIODevice fichier *) fonction
  5. Rechercher la ligne:

    // 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 le nouveau code source. Le fichier exécutable moc est généré dans le dossier/bin (si vous utilisez Windows, regardez c: /bin/moc.exe)

  7. Allez à Qt bin (C: \ Qt \ Qt5.0.1 \ 5.0.1 \ msvc2010 \ bin) et renommer le fichier exécutable moc moc.exe.bak

  8. Copiez le nouveau fichier exécutable moc dans le dossier bin Qt.

  9. Dans votre application actuelle, vous devez créer une macro par exemple:

    #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 
    

Enfin je vous laisse mon propre code source de replaceCustomMacros fonction:

Cette fonction convertir Q_SERVICE_INFO (méthode, chemin, type) macro à Q_CLASSINFO ("srv: // méthode", "type: chemin")

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

Je n'ai pas trouvé de solution spécifique sur Internet alors j'ai posté cette solution.

Bonne chance :)