IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Verdigris, une bibliothèque pour utiliser Qt sans générateur de métaobjets
Elle n'exploite que des en-têtes et des fonctionnalités de C++11

Le , par dourouc05

5PARTAGES

9  0 
Qt est un framework C++ complet, parti des interfaces graphiques dans les années 1990 (avant la normalisation de C++) et maintenant extrêmement généraliste. L’un de ses points forts est probablement la connexion entre signaux et slots pour écrire des applications interactives : lorsqu’il se passe quelque chose dans l’application (l’utilisateur appuie sur un bouton, un paquet arrive du réseau, etc.), un signal est émis ; ensuite, le programmeur peut connecter un slot à ce signal : ce bout de code sera exécuté chaque fois que le signal sera émis. Pour implémenter cette fonctionnalité, dans les années 1990, vu l’état disparate des compilateurs, utiliser les templates C++ était impossible : les développeurs de Qt ont alors utilisé un générateur de code, nommé moc (metaobject compiler), qui sert d’autres objectifs (l’introspection et la réflexion, notamment). Avec les années, le système a été conservé, malgré le bon nombre de critiques : son importance a encore un peu grandi lors de l’arrivée de Qt Quick. Olivier Goffart, actuel mainteneur de l’outil, tente de remettre les pendules à l’heure.

Quelques mythes

moc ne réécrit pas le code
qui lui est passé, il ne le réécrit pas : il l’analyse et génère de nouveaux fichiers C++, qui sont ensuite compilés de manière totalement indépendante. Sans l’outil, pour utiliser l’architecture actuelle de Qt, il serait nécessaire d’écrire de grandes quantités de code pour les tables d’introspection et d’autres détails nécessaires pour le fonctionnement des signaux et slots.

Il se concentre sur une série de macros définies par Qt pour générer son code : Qt ne définit pas de « nouveaux mots clés » C++. Pour définir une classe héritant de QObject, la macro Q_OBJECT évite au programmeur d’écrire une série de déclarations de fonctions (dont le code est généré par moc). Les signaux sont définis dans un bloc signals:, qui n’est autre qu’une macro qui correspond à public:. Bon nombre d’autres macros utilisées par le moc ne génèrent aucun code. Globalement, le code Qt reste du code C++, ce qui fait que tous les outils C++ traditionnels restent utilisables.

Son utilisation ne complique pas la compilation ou le débogage : la plupart des systèmes de compilation traitent de manière native moc  ; de toute façon, il s’agit simplement d’une commande supplémentaire à appliquer sur les fichiers d’en-tête. En cas d’erreur à la compilation (ce qui est très rare), le code généré est plus facile à comprendre que l’embrouillamini généré par les templates C++.

Certains ont tenté de supprimer moc, comme CopperSpice, en promettant notamment une amélioration de performance. Cependant, cette affirmation n’est pas sous-tendue par des chiffres : le graphique ci-dessous indique que la taille des exécutables générés est bien plus grande avec CopperSpice (sans moc) que Qt (4 ou 5, avec moc). De manière générale, le code généré par moc est très efficace : il est entièrement statique et évite toute allocation dynamique de mémoire, ses données sont stockées dans les segments de données en lecture seule — là où CopperSpice génère ces mêmes données à l’exécution.



Finalement, moc évolue : depuis Qt 5, il gère complètement les macros, ce qui permet de les utiliser pour définir des signaux, des slots, des classes de base, etc. Q_PROPERTY n’autorisait pas, jusqu’il y a peu, les virgules dans ses arguments (par exemple, en lui passant un QMap), ce qui a été réglé en un rien de temps.

Des fonctionnalités absentes

Finalement, la plus grande critique de moc est probablement qu’il ne gère pas les classes avec des templates, des classes imbriquées ou l’héritage multiple. Cependant, si elles ne sont pas implémentées, c’est principalement parce qu’elles ne sont pas jugées importantes. Par exemple, une implémentation des templates a été rejetée il y a trois ans ; moc-ng, une implémentation de moc sous la forme d’extension du compilateur Clang, gère sans problème les templates et les classes imbriquées. L’héritage multiple reste possible à condition que QObject soit la première classe de base — ce qui permet bon nombre d’optimisations, de telle sorte que qobject_cast est bien plus rapide que la version standard dynamic_cast.

Et donc ?

moc n’est pas vraiment un problème, ses plus grands pourfendeurs sont généralement ceux qui le connaissent le moins. L’API et notamment le système de métaobjets et la connexion entre signaux et slots sont à la base du succès de Qt. Les avantages des autres solutions sont loin d’être clairs et moc n’est pas une limitation pour les développeurs.

Source : Moc myths debunked.
Ce contenu a été publié dans Qt par dourouc05.
Vous avez lu gratuitement 0 articles depuis plus d'un an.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de tbrezi
Nouveau Candidat au Club https://www.developpez.com
Le 28/05/2016 à 7:09
verdigri semble utiliser des fonctionnalités du c++14, notamment les variable templates.
0  0 
Avatar de renoo
Membre éprouvé https://www.developpez.com
Le 28/05/2016 à 23:23
La syntaxe ne parait pas si tordu que ça. Ca a l'air bien.
0  0 
Avatar de kiruahxh
Nouveau membre du Club https://www.developpez.com
Le 25/05/2019 à 9:34
Citation Envoyé par Aurelien.Regat-Barrel Voir le message
Les projets VS sont en fait des fichiers MSBuild qui est le système de build de MS (VS est grosso modo un front end graphique pour MSBuild). Le souci c'est que par défaut, au niveau d'un même projet, les tâches de build ne sont pas parallélisées - les builds des projets le sont mais pas les tâches au sein des projets. L'exception à cela c'est les tâches de compilation car c'est le compilo qui se fork lui-même pour traiter les demandes en parallèle (et non MSBuild qui fait le boulot). Aussi pour des tâches genre moc, pas de parallélisation automatique. Et quand y'a des milliers de fichiers à moc'er, ben ça se sent! Pour s'en sortir il faut développer son propre outil qui va exécuter moc en parallèle et donc customiser la génération des projets au lieu de passer par qmake

Pour ne pas que le nombre de cpp à compiler double, la parade est de faire un include de son fichier moc depuis le code cpp. Ainsi qmake ne génère pas une step supplémentaire de build vu que le fichier généré est inclus dans le cpp d'origine. Ca marche pour toutes les plateformes, mais c'est un peu plus contraignant pour le programmeur. L'option plus "automatique" c'est de faire un unity build des fichiers moc générés pour les compiler tous d'un coup. Mais ça demande de développer un outil pour cela (il parait que CMake sait le faire).
J'ai développé un outil pour QMake pour faire automatiquement un unity build des CPP / MOC / MOC_CPP
Je crois que c'est toi qui m'a mis en tête que c'était possible de grouper les MOCS, j'ai testé et ça a marché
Les perfs sont top. https://github.com/nmoreaud/qmake-unity
Petit benchmark ici : https://github.com/nmoreaud/qmake-un...y#performances

Dans mon outil on peut soit grouper les fichiers moc_XXX.cpp (il reste X appels à MOC et 1 appel au compilo), soit grouper directement les classes à moccer (1 appel à MOC par groupe, et 1 appel au compilo).
Je sais que la première option marche nickel parce que je l'ai utilisé sur un gros projet pendant quelque temps ; la seconde option est à tester pour voir l'impact au quotidien...

Cela dit, je n'ai pas pris en charge MSVC (IDE), mais de souvenir ça marche bien pour MSBuild en ligne de commande.
Si quelqu'un veut développer la prise en charge de MSVC/XCode, je suis preneur : je ne travaillerai surement plus sur un gros projet C++ avant quelque temps...

Autre bonne nouvelle : d'après ce POST, Qt Visual Studio Tools >= 2.2 prend désormais en charge l'invocation en parallèle de MOC : https://blog.qt.io/blog/2018/02/26/q...-2-0-released/
0  0