<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Blog de Julian Ibarz &#187; C++</title>
	<atom:link href="https://blog.developpez.com/tanek/pcategory/informatique/langage/c/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/tanek</link>
	<description></description>
	<lastBuildDate>Sun, 08 Feb 2009 23:27:29 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>CxxTest et CMake</title>
		<link>https://blog.developpez.com/tanek/p7195/informatique/title_118</link>
		<comments>https://blog.developpez.com/tanek/p7195/informatique/title_118#comments</comments>
		<pubDate>Sun, 08 Feb 2009 23:25:05 +0000</pubDate>
		<dc:creator><![CDATA[tanek]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[CMake]]></category>
		<category><![CDATA[CxxTest]]></category>
		<category><![CDATA[Informatique]]></category>
		<category><![CDATA[Tests Unitaires]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Je n&#8217;ai jamais réellement fait de test unitaire en C++ voir dans n&#8217;importe quel langage du tout et je commence de plus en plus à réutiliser des codes que je fais il y a souvent très longtemps, je les retouche et je rajoute un bug et j&#8217;ai à chaque fois du mal à l&#8217;identifier (obligé de retester les fonctions une par une, re faire du code de test que j&#8217;avais parfois déjà fais, etc.). Bref [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Je n&rsquo;ai jamais réellement fait de test unitaire en C++ voir dans n&rsquo;importe quel langage du tout et je commence de plus en plus à réutiliser des codes que je fais il y a souvent très longtemps, je les retouche et je rajoute un bug et j&rsquo;ai à chaque fois du mal à l&rsquo;identifier (obligé de retester les fonctions une par une, re faire du code de test que j&rsquo;avais parfois déjà fais, etc.). Bref si vous aussi vous êtes dans ma situation, que vous cherchez une solution pour aller plus vite, vous avez sûrement déjà entendu parlé des tests unitaires et des frameworks disponibles en C++ pour automatiser tout ça. Si ce n&rsquo;est pas le cas je vous conseille d&rsquo;aller lire cet article qui propose une comparaison des frameworks les plus connus :<br />
<a href="http://gamesfromwithin.com/?p=29"><br />
Dan Crevier&rsquo;s Blog : A comparison of C++ unit testing frameworks (en anglais)</a></p>
<p>Après l&rsquo;avoir lu, vous faites comme moi confiance à l&rsquo;auteur et choisissez la bibliothèque CxxTest et essayez de l&rsquo;intégrer dans votre application. Si vous aussi vous utilisez CMake comme outil de construction, vous aurez remarqué que l&rsquo;intégration de CxxTest est plus que sommaire, je vous propose donc une solution plus complète.</p>
<p><span id="more-7"></span></p>
<p>Nous allons supposer que vous avez organisé vos fichiers comme suit :</p>
<ul>
<li>dossier src : contient toutes les sources ainsi que vos headers ;</li>
<li>dossier test : va contenir vos tests unitaires ;</li>
<li>dossier build : contiendra le fichier généré par CxxTest (il est très important que le dossier existe).</li>
</ul>
<p>Voici maintenant un build minimaliste avec quelques commentaires pour vous expliquer son fonctionnement :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">cmake_minimum_required(VERSION 2.6) &nbsp;<br />
&nbsp;<br />
#Configuration du projet &nbsp;<br />
project(mon-projet) &nbsp;<br />
set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE}) &nbsp;<br />
&nbsp;<br />
# Va permettre de pouvoir trouver Find &nbsp;<br />
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} &quot;.&quot;) &nbsp;<br />
&nbsp;<br />
# Fait la liaison avec la bibliothèque CxxTest &nbsp;<br />
FIND_PACKAGE(CxxTest REQUIRED) &nbsp;<br />
SET(CXXTEST_USE_PYTHON 1) &nbsp;<br />
&nbsp;<br />
file( &nbsp;<br />
&nbsp; GLOB_RECURSE &nbsp;<br />
&nbsp; source_files &nbsp;<br />
&nbsp; src/*.cpp &nbsp;<br />
&nbsp; src/*.hpp &nbsp;<br />
&nbsp;) &nbsp;<br />
&nbsp;<br />
&nbsp;<br />
file( &nbsp;<br />
&nbsp; GLOB_RECURSE &nbsp;<br />
&nbsp; test-files &nbsp;<br />
&nbsp; test/*.hpp &nbsp;<br />
&nbsp;) &nbsp;<br />
&nbsp;<br />
&nbsp;<br />
# Unit testing &nbsp;<br />
ENABLE_TESTING() &nbsp;<br />
CXXTEST_ADD_TEST(unit-test build/mon-test-unitaire.cpp ${test-files}) &nbsp;<br />
&nbsp;<br />
add_executable( &nbsp;<br />
&nbsp; test-unit &nbsp;<br />
&nbsp; build/mon-test-unitaire.cpp &nbsp;<br />
) &nbsp;<br />
&nbsp;<br />
add_library( &nbsp;<br />
&nbsp; lib-mon-projet STATIC &nbsp;<br />
&nbsp; ${source_files} &nbsp;<br />
) &nbsp;<br />
&nbsp;<br />
add_executable(mon-projet &nbsp;<br />
&nbsp; src/main.cc &nbsp;<br />
) &nbsp;<br />
&nbsp;<br />
include_directories( &nbsp;<br />
&nbsp; &quot;src&quot; &nbsp;<br />
&nbsp; &quot;.&quot; #Nécessaire pour CxxTest &nbsp;<br />
&nbsp; ${CXXTEST_INCLUDE_DIR} &nbsp;<br />
) &nbsp;<br />
&nbsp;<br />
#Configuration de l'édition de liens &nbsp;<br />
target_link_libraries( &nbsp;<br />
&nbsp; test-unit &nbsp;<br />
&nbsp; lib-mon-projet &nbsp;<br />
) &nbsp;<br />
&nbsp;<br />
target_link_libraries( &nbsp;<br />
&nbsp; mon-projet &nbsp;<br />
&nbsp; lib-mon-projet &nbsp;<br />
)</div></div>
<p>Tout d&rsquo;abord vous aurez besoin du fichier FindCxxTest.cmake que j&rsquo;ai repiqué d&rsquo;<a href="http://public.kitware.com/cgi-bin/viewcvs.cgi/Modules/FindCxxTest.cmake?root=CMake&#038;view=markup">ici</a> et &laquo;&nbsp;amélioré&nbsp;&raquo;. Ma version se trouve <a href="http://prologia.svn.sourceforge.net/viewvc/prologia/iupsi/ter/FindCxxTest.cmake?view=markup">ici</a>.</p>
<p>Pourquoi l&rsquo;avoir modifié ? Et bien parce que la version normale suppose que notre programme test n&rsquo;ait pas besoin de l&rsquo;ensemble de notre projet pour fonctionner or normalement quand vous faites un test unitaire sur une classe très importante, vous aurez besoin de la définition de presque toutes vos classes. La version normale ne vous permet pas cela.</p>
<p>Comment alors faire pour linker notre test unitaire à notre programme ? La première chose serait de faire un exécutable contenant toutes les sources de notre projet sauf le fichier contenant la fonction main (main.cc) :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">add_executable( &nbsp;<br />
&nbsp; test-unit &nbsp;<br />
&nbsp; build/bspline.cpp &nbsp;<br />
&nbsp; ${source_files} &nbsp;<br />
) &nbsp;<br />
&nbsp;<br />
add_executable(mon-projet &nbsp;<br />
&nbsp; src/main.cc &nbsp;<br />
&nbsp; ${source_files} &nbsp;<br />
)</div></div>
<p>Vous comprenez au passage pourquoi j&rsquo;ai décidé de prendre l&rsquo;extension main.cc au lieu de cpp, quand je fais ma liste de sources :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">file( &nbsp;<br />
&nbsp; GLOB_RECURSE &nbsp;<br />
&nbsp; source_files &nbsp;<br />
&nbsp; src/*.cpp &nbsp;<br />
&nbsp; src/*.hpp &nbsp;<br />
&nbsp;)</div></div>
<p>Je prends ainsi automatiquement toutes les sources de mon projet sauf le fichier main.cc&#8230;</p>
<p>Le problème avec cette solution est qu&rsquo;elle va faire compiler tous nos fichiers deux fois (une fois pour test-unit et une autre fois pour mon-projet. Pour éviter cela il suffit de faire une bibliothèque statique temporaire et de la linker aux deux comme proposé dans ma solution ; ainsi les fichiers ne seront compilés qu&rsquo;une fois.</p>
<p>Et voilà, l&rsquo;intégration est terminée ! On peut sûrement amélioré tout ceci et je vous encourage à me contacter si vous avez trouvé quelque chose de plus élégant :).</p>
<p><em>Attention : </em>Bien sûr je suppose que vous avez mis dans les variables d&rsquo;environnements le dossier d&rsquo;include de CxxTest et le dossier racine pour trouver les scripts python. Voici comment c&rsquo;est chez moi :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">export PATH=$PATH:/home/tanek/Logiciels/cxxtest <br />
export CMAKE_INCLUDE_PATH=$CMAKE_INCLUDE_PATH:/home/tanek/Logiciels/cxxtest/cxxtest</div></div>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Le parsing de fichier, une prise de tête ?</title>
		<link>https://blog.developpez.com/tanek/p7110/informatique/le_parsing_de_fichier_une_prise_de_tete</link>
		<comments>https://blog.developpez.com/tanek/p7110/informatique/le_parsing_de_fichier_une_prise_de_tete#comments</comments>
		<pubDate>Fri, 23 Jan 2009 00:31:23 +0000</pubDate>
		<dc:creator><![CDATA[tanek]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[Informatique]]></category>
		<category><![CDATA[yacc/lex ou bison/flex]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Le parsing de fichier est souvent une tâche ingrate et compliquée que l&#8217;on doit parfois faire pour charger des données dans un certain format. Alors il existe maintenant le standard XML qui permet de mâcher le travail grâce aux APIs DOM et compagnie mais parfois on se retrouve avec des formats anciens non XML ou tout simplement le XML n&#8217;est pas adapté (fortes contraintes de performance, etc.). Souvent la solution que prennent la majorité des [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Le parsing de fichier est souvent une tâche ingrate et compliquée que l&rsquo;on doit parfois faire pour charger des données dans un certain format. Alors il existe maintenant le standard XML qui permet de mâcher le travail grâce aux APIs DOM et compagnie mais parfois on se retrouve avec des formats anciens non XML ou tout simplement le XML n&rsquo;est pas adapté (fortes contraintes de performance, etc.).</p>
<p>Souvent la solution que prennent la majorité des gens (y compris moi) est de faire un analyseur tout à la main j&rsquo;entends par là qu&rsquo;on se met à écrire plein de code qui coupe le fichier en ligne, qui coupe la ligne en petit morceau, qui teste les petits morceaux, les regroupe, les mélange, fait des conversions chaîne données, fait des blocs if else de partout, etc. et on en arrive finalement, pardonnez-moi l&rsquo;expression, à un vrai merdier. Et parfois cela peut aller très loin comme je vais vous l&rsquo;expliquer un peu plus loin. Mais pourquoi je vous parle de tout ça ? Mais à cause du raytracer bien sûr ! Quoi, Vous ne comprenez pas le lien ? Je vous explique&#8230;</p>
<p><span id="more-6"></span></p>
<p><strong>Les graphistes n&rsquo;aiment pas le libre et les programmeurs ne savent pas desssiner !</strong></p>
<p>Après avoir affiché mes 3 sphères dans mon raytracer en temps réel (voir le précédent billet), j&rsquo;ai décidé qu&rsquo;il serait temps de charger quelque chose de plus gros pour voir jusqu&rsquo;où on pouvait aller sans optimisation.</p>
<p>Je me suis donc renseigné sur les scènes disponibles sur le net gratuitement et fort est de constater que je n&rsquo;en ai pas trouvé ! J&rsquo;ai trouvé quelques modèles par ci par là, rarement texturés mais jamais de scène entière 3D (si vous en connaissez, n&rsquo;hésitez pas à me contacter !). Après discussion avec l&rsquo;un de mes professeurs de rendu 3D, il m&rsquo;a clairement dit que vu qu&rsquo;ils n&rsquo;avaient pas de graphistes dans leurs équipes, ils étaient obligés d&rsquo;acheter des scènes lorsqu&rsquo;ils voulaient faire des démos de leurs algorithmes de rendus. C&rsquo;est surprenant mais en fait assez logique : comme presque tous les programmeurs 3D, je suis incapable de dessiner un simple modèle sous blender ou de créer une texture :D.</p>
<p>J&rsquo;en ai donc profité pour lui demander une des scènes qu&rsquo;ils avaient acheté. Le format de la scène est un format obj somme toute pas très compliqué et de type texte (comprendre : les données ne sont pas stockées en binaire) mais assez pour pouvoir se prendre la tête. En même temps j&rsquo;en ai profité pour lui demander s&rsquo;il n&rsquo;avait pas un loader de fichier obj histoire de ne pas avoir à le faire et c&rsquo;est là qu&rsquo;il me file carrément un visualiseur de scène obj. Je n&rsquo;en demandais pas tant !</p>
<p><strong>Couper un coeur avec des geometry shaders ?</strong></p>
<p>Entre temps j&rsquo;ai quelqu&rsquo;un qui me demande de lui faire une démo de coupe de modèles 3D de coeur pas simplement suivant un plan (car un simple clip plane aurait suffit) mais suivant des fonctions de décision plus complexes (coupe sphérique, cylindrique, etc.) histoire de faire plaisir aux docteurs et qu&rsquo;ils puissent couper de façon plus personnaliser le coeur et voir dedans. Et grande chance : le format du modèle est aussi le format obj. Mais comme cela arrive souvent en informatique, j&rsquo;essaye de le visualiser et cela ne marche pas. Que se passe-t-il ? Et bien apparemment le format du modèle 3D ne respecte pas strictement le format officiel et le parser le rejette.</p>
<p><strong>Où l&rsquo;encapsulation de code permet parfois de cacher des horreurs</strong></p>
<p>Je me décide donc à ouvrir le capôt, en l&rsquo;occurence à regarder le code du parser plus en détail et là c&rsquo;est un véritable monstre que je vois : le parser est en gros constitué d&rsquo;une fonction de pas moins de 2000 lignes de code illisibles, pouvant atteindre à certains endroits un niveau d&rsquo;imbrication de 5 ou 6 if/else à la suite, des copiés collés en veux-tu, en voilà, utilisant mal et inutilement des templates variadics (voir la prochaine norme du C++0x), bref du code qui marche que sur la dernière version de gcc et même pas sur la dernière version de vc++ et qui ne marchera plus quand le C++0x sortira. Génial, je ne pensais pas que cela soit possible. Qu&rsquo;à cela ne tienne, je modifie le parser pour qu&rsquo;il arrive à lire mon obj et je me dis que j&rsquo;en ai fini avec ça.</p>
<p><strong>Du GNU GPL qui n&rsquo;est pas libre</strong></p>
<p>Mais voilà ces satanés licences qui continuent de m&rsquo;embêter ! En effet, Je le préviens que j&rsquo;ai mis son visualiseur sur le site de gitorious avec mon raytracer car je développe sur 3 PCs (mon portable qui n&rsquo;a pas CUDA mais qui me permet de coder tranquilou quelques trucs, à la fac où j&rsquo;ai CUDA et où j&rsquo;en profite pour tester mon code fait la veille et enfin chez mes parents le week-end où j&rsquo;ai un PC fixe avec CUDA) et que cela me facilite la vie. Mais voilà, même si les en-têtes de fichiers indiquent clairement que le code est sous licence GNU GPL, il me dit que le code du loader OBJ ne doit pas être accessible sur l&rsquo;Internet car en fait il n&rsquo;est pas sous licence libre. Entre le fait que le code soit horrible et qu&rsquo;il soit protégé, s&rsquo;en est trop, je décide de le réécrire.</p>
<p>Finalement, une fois avoir terminé mon parser, je me suis rendu compte que le parser de mon prof était en fait celui-ci :</p>
<p>http://www.cs.kuleuven.ac.be/~ares/libobj/index.html</p>
<p>Et qui est en fait en GNU GPL. D&rsquo;ailleurs si vous l&rsquo;utilisez, je vous encourage à utiliser plutôt le miens car il est quand même deux fois plus rapide (voir plus loin).</p>
<p><strong>Un compilateur qui fait un compilateur, ou le problème de la poule et de l&rsquo;oeuf ?</strong></p>
<p>Je décide donc de me renseigner sur des techniques pour simplifier le code. je commence par jeter un oeil sur boost regexp qui permet de faire des analyses de chaîne en utilisant les expressions régulières. Comme d&rsquo;habitude avec boost, c&rsquo;est très puissant et très concis d&rsquo;utilisation. J&rsquo;arrive à supprimer quelques centaines de lignes mais j&rsquo;arrive à un stade où l&rsquo;utilisation seule des expressions régulières n&rsquo;est plus suffisante et où il faudrait pouvoir définir une règle de grammaire pour analyser différents cas possibles pour un même type de donné. De plus, je n&rsquo;arrive pas à rejoindre les performances du parseur d&rsquo;origine (qui est codé cradement mais qui est sacrément rapide : il charge ma scène en 23 secondes et je n&rsquo;arrive qu&rsquo;à 45 secondes avec mes expressions régulières sachant que je ne les ai utilisé que pour le quart de l&rsquo;analyse, je me dis que si je continue comme ça, j&rsquo;arriverai à un code un peu plus simplifié mais qui me chargerait la scène en 2 minutes ce qui n&rsquo;est pas acceptable).</p>
<p><strong>Le flex du bison fait des calculatrices&#8230;</strong></p>
<p>Je décide alors de changer de fusil d&rsquo;épaule, je regarde dans les technologies de génération de compilateurs. Je regarde s&rsquo;il en existe pour le langage C++ en licence permissive (LGPL, BSD-like, histoire de pouvoir le réutiliser dans un contexte professionnel fermé si besoin est) mais je n&rsquo;en trouve aucune. Je regarde ensuite pour le langage C et j&rsquo;en trouve quelques uns. J&rsquo;avais le choix entre antlr et yacc/lex. J&rsquo;ai choisi yacc/lex, allez savoir pourquoi. Et finalement j&rsquo;ai choisi bison/flex (qui est lui en licence GPL) car les seuls exemples à la &laquo;&nbsp;hello world&nbsp;&raquo; version génération de compilation (comprendre créer une calculatrice qui sait faire des additions et des multiplications, youhou !) que j&rsquo;ai trouvé étaient pour lui (mais apparemment il utilise la même syntaxe que yacc/lex donc ce sera facilement portable). Et puis les paquets sont souvent installés partout à la différence de yacc/lex.</p>
<p><strong>&#8230;et il cours très vite !</strong></p>
<p>J&rsquo;installe le monstre en quelques secondes (vive linux et les packages) et je commence à tester la bête. Il me faut une journée pour créer un analyseur de fichier obj minimaliste (comprendre qu&rsquo;il ne gère pas toute la syntaxe), environ 200 lignes de code ma fois assez claires et je commence à tester ses performances et là bonne surprise : il explose les perfs (6.5 secondes pour parser le fichier !).</p>
<p>Après deux bons jours de développement, j&rsquo;arrive à finir mon parseur et à le connecter à mon visualiseur et j&rsquo;arrive à un parsing de l&rsquo;ordre de 8 secondes au lieu de 22. Et même au niveau de la taille du code, je le divise par trois et il est bien plus clair !</p>
<p>Si vous voulez télécharger ce projet, tappez les commandes suivantes :</p>
<p>git clone http://git.gitorious.org/personal-julian-ibarz/math.git<br />
git clone http://git.gitorious.org/personal-julian-ibarz/obj-parser.git<br />
git clone http://git.gitorious.org/personal-julian-ibarz/obj-viewer.git</p>
<p>Ensuite allez dans les différents projets (math, ensuite obj-parser et enfin obj-viewer) et tappez :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">cmake . <br />
make</div></div>
<p>Vous n&rsquo;avez plus qu&rsquo;à tester avec une scène obj que vous avez ! Si ça ne marche pas, n&rsquo;hésitez pas à me contacter !</p>
<p><strong>Pièges à éviter</strong></p>
<p>J&rsquo;ai eu quelques problèmes en utilisant bison/flex et j&rsquo;aimerais vous les faire partager. Il faut tout d&rsquo;abord faire attention au fait que le retour à la ligne sous windows est &laquo;&nbsp;\r\n&nbsp;&raquo; et sous linux &laquo;&nbsp;\n&nbsp;&raquo;. Ensuite si vous vous amusez à parser des flottants, il faudra bien faire attention à mettre la locale par défaut. Voici un bout de code qui montre comment faire :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; string backupLocale = setlocale( LC_NUMERIC, NULL); <br />
&nbsp; &nbsp; setlocale(LC_NUMERIC, &quot;C&quot;); <br />
&nbsp;<br />
&nbsp; &nbsp; FILE* fileIn = freopen(filePath.c_str(), &quot;r&quot;, stdin); <br />
&nbsp; &nbsp; // TODO return an exception <br />
&nbsp; &nbsp; assert(fileIn); <br />
&nbsp; &nbsp; yyparse(); <br />
&nbsp; &nbsp; fclose(fileIn); <br />
&nbsp; &nbsp; setlocale(LC_NUMERIC, backupLocale.c_str());</div></div>
<p>Enfin, pour l&rsquo;analyse syntaxique, il faut absolument que vos différents types de mots n&rsquo;aient pas de collision. J&rsquo;entends par là que si vous définissez par exemple les entiers et les flottants comme suit :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">unsigned_integer_const &nbsp; &nbsp;{numeral_const}+ <br />
sign_const [+-] <br />
integer_const {sign_const}?{unsigned_integer_const} <br />
exposant_const &nbsp;[eE]{integer_const} <br />
float_const &nbsp; &nbsp;{integer_const}(&quot;.&quot;?{unsigned_integer_const}?){exposant_const}?</div></div>
<p>Cela ne marchera pas car si vous définissez la capture du flottant en premier, tous les entiers seront transformés en flottant. Pour éviter cela, vous devez forcer la détection du point (enlever ? après le point) quitte ensuite à gérer dans l&rsquo;analyse syntaxique le cas où un flottant a été reconnu comme un entier :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">real_exp: <br />
&nbsp; &nbsp; FLOAT { $$ = $1; } <br />
&nbsp; &nbsp; | UNSIGNED_INTEGER { $$ = (float)$1; } <br />
&nbsp; &nbsp; | INTEGER { $$ = (float)$1; }</div></div>
<p>Enfin, ne jamais utiliser l&rsquo;expression régulière suivant &laquo;&nbsp;.*&nbsp;&raquo; car sinon votre parser va analyser tout votre fichier d&rsquo;un coup et va même faire un segfault. Si vous voulez parser toute une ligne jusqu&rsquo;à la fin vous pouvez utiliser &laquo;&nbsp;[^\n]*&nbsp;&raquo;. Ensuite si vous avez besoin de changer la façon dont votre parser analyse la chaîne suivant qu&rsquo;il est dans un commentaire par exemple (on ne veut pas s&rsquo;il y a un nombre qu&rsquo;il dise qu&rsquo;il a trouvé un nombre), vous devrez utiliser les exclusions :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">%x READ_LINE <br />
[...] <br />
%% <br />
[...] <br />
&quot;#&quot; { BEGIN(READ_LINE); return COMMENTAIRE; } <br />
&lt;READ_LINE&gt;[^\n]* { yylval.string_val = new std::string(yytext); STRING_LINE; } <br />
&lt;READ_LINE&gt;\n { BEGIN(INITIAL); yylineno++; return END_LINE; }</div></div>
<p>Je vous laisse le soin d&rsquo;aller voir la doc officielle pour plus de détails.</p>
<p>Enfin, si vous programmez en C++ et si vous utilisez flex/bison et non pas flex++/bison++, je vous conseille fortement de ne pas utiliser un pattern singleton car vous allez galérer pour accéder aux données de votre parser. Préférez un pattern module :</p>
<p>Dans parser-private.h on fait comme si c&rsquo;était de portée privée</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">namespace monparser <br />
{ <br />
&nbsp; &nbsp; extern Type monMembrePrive; <br />
[...] <br />
};</div></div>
<p>Dans parser.h il y a tout ce qui est de portée publique</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">namespace monparser <br />
{ <br />
&nbsp; &nbsp; void initialise(void); <br />
&nbsp; &nbsp; Type&amp; getMonMembre(void); <br />
&nbsp; &nbsp; [...] <br />
&nbsp; &nbsp; void delete(void); <br />
}</div></div>
<p>Dans parser.cpp :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">#include &quot;parser-private.h&quot; <br />
#include &quot;parser.h&quot; <br />
&nbsp;<br />
Type objparser::monMembrePrive; // On instancie notre membre <br />
&nbsp;<br />
void objparser::initialise(void) <br />
{ &nbsp;<br />
&nbsp; &nbsp;// On initialise les membres <br />
}</div></div>
<p>Pour ceux qui ont &laquo;&nbsp;Le langage C++&nbsp;&raquo; de Bjarne Soustrup, il l&rsquo;explique très bien. Cela permettre de pouvoir accéder directement aux membres dans les fichiers parser.y et parser.lex de cette manière :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">using namespace parser; <br />
[...] <br />
monMembrePrive <br />
[...]</div></div>
<p>Au lieu de faire si vous aviez utilisé un singleton :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">parser::getInstance().getMonMembrePrive()</div></div>
<p>En plus c&rsquo;est pas terrible niveau performance. Quelle est la motivation d&rsquo;accéder directement aux données ? et bien parce que je considère que les fichiers parser.lex et parser.y sont en fait l&rsquo;implémentation de mon parser donc c&rsquo;est normal de pouvoir accéder directement à mes données&#8230;</p>
<p>Voilà pour les astuces, j&rsquo;espère que ça vous sera utile !</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Découverte de CUDA</title>
		<link>https://blog.developpez.com/tanek/p7109/informatique/raytracer/decouverte_de_cuda</link>
		<comments>https://blog.developpez.com/tanek/p7109/informatique/raytracer/decouverte_de_cuda#comments</comments>
		<pubDate>Fri, 23 Jan 2009 00:27:25 +0000</pubDate>
		<dc:creator><![CDATA[tanek]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[CUDA]]></category>
		<category><![CDATA[raytracer]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Cela faisait plusieurs mois que j&#8217;étais attiré par la technologie CUDA et ses possibilités. Je me suis donc lancé pendant les vacances de Noël à faire un raytracer en temps réel (comprendre par là plus de 24 images par seconde) en utilisant CUDA. CUDA et les ray-tracers Je m&#8217;étais déjà fait les dents sur un mini-raytracer en Java en suivant l&#8217;excellentissime tutoriel de LeGreg et j&#8217;étais arrivé aux performances de 700ms sur un simple rendu [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Cela faisait plusieurs mois que j&rsquo;étais attiré par la technologie CUDA et ses possibilités. Je me suis donc lancé pendant les vacances de Noël à faire un raytracer en temps réel (comprendre par là plus de 24 images par seconde) en utilisant CUDA.</p>
<p><span id="more-5"></span></p>
<p><strong>CUDA et les ray-tracers</strong></p>
<p>Je m&rsquo;étais déjà fait les dents sur un mini-raytracer en Java en suivant l&rsquo;excellentissime <a href="http://www.massal.net/article/raytrace/page1.html">tutoriel</a> de <a href="http://blog.developpez.com/legreg">LeGreg</a> et j&rsquo;étais arrivé aux performances de 700ms sur un simple rendu de 3 sphères avec une lumière en gérant les réflexions. Et comme d&rsquo;habitude, une fois le principe compris, je ne le finis pas et décida de passer à autre chose.</p>
<p>Mais, quelques mois plus tard, en lisant sur le forum <a href="http://ompf.org/forum/">ompf</a> (soi-dit en passant : une des meilleurs sources d&rsquo;informations pour le lancer de rayon en général) que certaines personnes avaient réussi à faire des raytracers en temps réel en CUDA. Là, la mouche me pique et je décide moi aussi d&rsquo;en faire un.</p>
<p>J&rsquo;ai donc commencé à me renseigner sur CUDA et 3 jours après j&rsquo;avais mes 3 boules sur l&rsquo;écran avec un rendu à 40 fps. Voici le résultat :</p>
<p><img src="http://ftp-developpez.com/julian-ibarz/blog/img/raytracing.png" alt="Capture d'écran du raytracer" title="Capture d'écran du raytracer" /></p>
<p>J&rsquo;étais donc satisfait : sans vraiment trop essayer d&rsquo;optimiser, j&rsquo;obtenais des performances bien meilleures que si je les avais faites sur un simple CPU (en sachant qu&rsquo;on peut faire beaucoup mieux). De plus, j&rsquo;ai été agréablement surpris par la transparence de CUDA et sa prise en main rapide.</p>
<p><strong>CUDA et le C++ (oui, oui&#8230; vous avez bien lu)</strong></p>
<p>Mais je ne me suis pas arrêté là, j&rsquo;ai décidé de pousser le compilateur nvcc jusqu&rsquo;à ses derniers retranchements après avoir découvert la bibliothèque <a href="http://code.google.com/p/stdcuda/">stdcuda</a> qui utilise CUDA avec du langage C++ et des templates ! En effet, officiellement, CUDA supporte le langage C avec quelques extensions dans les fonctions qui seront exécutées dans la carte graphique.</p>
<p>Que Nenni ! CUDA supporte en fait presque tout le C++ mis à part le polymorphisme (en effet, à cause de l&rsquo;architecture GPU, c&rsquo;est très difficile de faire du polymorphisme). Vous pouvez donc utiliser presque toute la puissance du C++ notamment la surcharge des opérateurs (j&rsquo;aime mes classes Real3 et Matrix4 dans mon code CUDA&#8230;) ce qui permet de simplifier énormément votre code et de le factoriser au maximum sans rien perdre en performance. Néanmoins, CUDA étant jeune, j&rsquo;ai réussi à faire planter le compilateur sur certains bouts de code et il faut avouer que parfois les messages d&rsquo;erreurs qu&rsquo;il nous renvoie sont carrément inutiles ou nous font chercher au mauvais endroit, ce qui est encore pire.</p>
<p><strong>CUDA et la non-édition de liens (oui, oui&#8230; là aussi vous avez bien lu :D)</strong></p>
<p>Dernier soucis et pas des moindres, CUDA ne supporte pas l&rsquo;édition de liens à la compilation. Vous ne pourrez donc pas séparer votre code en plusieurs fichiers .cu (vous pouvez par contre avoir autant de fichiers de déclarations que vous voulez) ou alors vous devrez vous assurer de tous les inclure dans un seul fichier (workaround dégueulasse, mais workaround qui fonctionne)&#8230; C&rsquo;est bien dommage mais je pense que dans les prochaines versions cette limitation sera corrigée, il n&rsquo;y a pas de raison.</p>
<p>En résumé : essayez CUDA ! Ce ne sera pas une perte de temps !</p>
<p><strong>Récupération du code source</strong></p>
<p>Vous pouvez récupérer le code source <a href="http://gitorious.org/projects/personal-julian-ibarz/repos/mainline">ici</a>. Ou essayez une de ces commandes :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">git clone git://gitorious.org/personal-julian-ibarz/mainline.git <br />
git clone http://git.gitorious.org/personal-julian-ibarz/mainline.git</div></div>
<p>Il y a également un viewer de source par navigateur web sur le site web.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IDE pour Qt en C++</title>
		<link>https://blog.developpez.com/tanek/p6770/informatique/langage/c/ide_pour_qt_en_c</link>
		<comments>https://blog.developpez.com/tanek/p6770/informatique/langage/c/ide_pour_qt_en_c#comments</comments>
		<pubDate>Mon, 10 Nov 2008 19:10:29 +0000</pubDate>
		<dc:creator><![CDATA[tanek]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[Qt]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Il est dépriment de voir à quel point les IDE libres pour le langage C++ sont si peu avancés. En tout cas pas au point d&#8217;égaler les IDEs Netbeans et Eclipse pour Java. Néanmoins, il existe maintenant des plug-ins C/C++ pour Netbeans et Eclipse et bien que celui de Netbeans ne soit pas encore très avancé (la complétion ne marche pas encore très bien), celui d&#8217;Eclipse est beaucoup plus stable (bien que la complétion des [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Il est dépriment de voir à quel point les IDE libres pour le langage C++ sont si peu avancés. En tout cas pas au point d&rsquo;égaler les IDEs Netbeans et Eclipse pour Java. Néanmoins, il existe maintenant des plug-ins C/C++ pour Netbeans et Eclipse et bien que celui de Netbeans ne soit pas encore très avancé (la complétion ne marche pas encore très bien), celui d&rsquo;Eclipse est beaucoup plus stable (bien que la complétion des classes génériques n&rsquo;ait pas l&rsquo;air de fonctionner). Il permet de faire du refactoring notamment renommer une classe, une variable, etc. ou de savoir dans quelles parties du code une méthode/fonction est utilisée, toute ces choses qui font augmenter la productivité et facilitent la vie du programmeur.</p>
<p>Et pour ceux qui utilisent Qt, il existe même un add-on pour importer un projet .pro automatiquement et faire pleins d&rsquo;autres choses. Seulement cela ne marche pas avec les dernières versions de logiciels et vous avez peut-être rencontré cette erreur :</p>
<blockquote><p>
Unable to satisfy dependency from com.trolltech.qtcpp.feature.feature.group 1.4.3 to requiredCapability: org.eclipse.equinox.p2.iu/com.trolltech.qtcpp.linux.x86/[4.4.1,4.4.1].</p></blockquote>
<p>Nous allons voir comment résoudre ce problème.</p>
<p><span id="more-4"></span></p>
<p>Tout d&rsquo;abord je vous réfère à la documentation existante pour installer la dernière version :</p>
<p>http://labs.trolltech.com/blogs/2007/07/11/develop-qt-applications-in-eclipse</p>
<p>Ensuite une fois que vous avez fait tout ce qu&rsquo;il faut, lors de l&rsquo;activation du plugin Qt, l&rsquo;intégration plante avec le message d&rsquo;erreur donné précédemment. Le problème vient du fait qu&rsquo;il attend la version 4.4.1 de com.trolltech.qtcpp.linux.x86 alors que si vous allez dans votre répertoire de eclipse vous trouverez la version 4.4.2 (eclipse/plugins/com.trolltech.qtcpp.linux.x86_4.4.2). Pour se faire, il suffit de modifier le fichier eclipse/features/com.trolltech.qtcpp.feature_1.4.3/feature.xml et de lui dire que ce n&rsquo;est pas la version 4.4.1 qu&rsquo;il doit attendre mais la 4.4.2 et le tour est joué !</p>
<p>Voici la modification à faire :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp;&lt;plugin <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;id=&quot;com.trolltech.qtcpp.linux.x86&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;os=&quot;linux&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ws=&quot;gtk&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;arch=&quot;x86&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;download-size=&quot;0&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;install-size=&quot;0&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;version=&quot;4.4.1&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fragment=&quot;true&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;unpack=&quot;false&quot;/&gt; <br />
&nbsp;<br />
&nbsp; &nbsp;&lt;plugin <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;id=&quot;com.trolltech.qtcpp.linux.x86_64&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;os=&quot;linux&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ws=&quot;gtk&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;arch=&quot;x86_64&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;download-size=&quot;0&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;install-size=&quot;0&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;version=&quot;4.4.1&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fragment=&quot;true&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;unpack=&quot;false&quot;/&gt;</div></div>
<p>Dans version changer la valeur 4.4.1 en 4.4.2.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
