<?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>Coder-Studio</title>
	<atom:link href="http://www.coder-studio.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.coder-studio.com/blog</link>
	<description></description>
	<lastBuildDate>Mon, 16 Apr 2012 09:48:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Utilisation de l&#039;API Stax de libXML2</title>
		<link>http://www.coder-studio.com/blog/utilisation-de-lapi-stax-de-libxml2/</link>
		<comments>http://www.coder-studio.com/blog/utilisation-de-lapi-stax-de-libxml2/#comments</comments>
		<pubDate>Mon, 28 Feb 2011 23:54:01 +0000</pubDate>
		<dc:creator>Calvin1602</dc:creator>
				<category><![CDATA[C & C++]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.coder-studio.com/blog/?p=500</guid>
		<description><![CDATA[Pour charger un fichier XML, il y a traditionnellement deux API : Sax et DOM

    * Sax oblige a écrire plein de callbacks. Ca fait tout ce dont on peut avoir besoin, mais c'est assez lourd à coder.
    * DOM chargeant tout en mémoire, ce n'est pas adapté pour les gros fichiers.
]]></description>
			<content:encoded><![CDATA[<p>Pour charger un fichier XML, il y a traditionnellement deux API : Sax et DOM</p>
<p>    * Sax oblige a écrire plein de callbacks. Ca fait tout ce dont on peut avoir besoin, mais c'est assez lourd à coder.<br />
    * DOM chargeant tout en mémoire, ce n'est pas adapté pour les gros fichiers.<br />
<span id="more-500"></span>;</p>
<h1>Introduction</h1>
<p>Le XML c'est génial, le XML c'est beau, le XML vous fait le cacao le matin.</p>
<p>Pour charger un fichier XML, il y a traditionnellement deux API : Sax et DOM</p>
<ul>
<li>Sax oblige a écrire plein de callbacks. Ca fait tout ce dont on peut avoir besoin, mais c'est assez lourd à coder.</li>
<li>DOM chargeant tout en mémoire, ce n'est pas adapté pour les gros fichiers.</li>
</ul>
<h1>Stax</h1>
<p>L'API de type Stax est un juste milieu entre des deux approches. L'idée, c'est qu'au lieu de laisser le parseur tout gérer, on va lui demander un élément, l'analyser nous-même, puis demander l'élément suivant.</p>
<p>La libxml2, du projet Gnome, fournit une API de ce type. Elle est plutôt bien documentée, mais les exemples, mêmes s'ils sont fonctionnels, ne sont pas très utiles tels quels : la plupart accèdent à un élément connu d'avance et listent ses propriétés. Généralement, quand on a un fichier XML tellement gros qu'on ne peut pas utiliser DOM, la problématique est plutôt : découvrir à la volée ce qu'on a dans le fichier.</p>
<h1>Fichier d'exemple</h1>
<p>Pour ce tutoriel, j'utiliserai des fichiers de dump OpenStreetMap, qui peuvent atteindre plusieurs centaines de Go. Un bon test pour les fuites mémoires...</p>
<p>En simplifié , ça ressemble à ça (ici sur un bout de granite près de Lannion) :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p500code1'); return false;">View Code</a> XML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p5001"><td class="code" id="p500code1"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span>  <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;osm</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;0.6&quot;</span>  <span style="color: #000066;">generator</span>=<span style="color: #ff0000;">&quot;CGImap 0.0.2&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bounds</span> <span style="color: #000066;">minlat</span>=<span style="color: #ff0000;">&quot;48.7640630&quot;</span>  <span style="color: #000066;">minlon</span>=<span style="color: #ff0000;">&quot;-3.5936820&quot;</span> <span style="color: #000066;">maxlat</span>=<span style="color: #ff0000;">&quot;48.7670190&quot;</span> <span style="color: #000066;">maxlon</span>=<span style="color: #ff0000;">&quot;-3.5882580&quot;</span>  <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;node</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;28204783&quot;</span>  <span style="color: #000066;">lat</span>=<span style="color: #ff0000;">&quot;48.7661740&quot;</span> <span style="color: #000066;">lon</span>=<span style="color: #ff0000;">&quot;-3.5946960&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;tag</span> <span style="color: #000066;">k</span>=<span style="color: #ff0000;">&quot;created_by&quot;</span>  <span style="color: #000066;">v</span>=<span style="color: #ff0000;">&quot;almien_coastlines&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/node<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    ... encore beaucoup de texte</pre></td></tr></table></div>

<p>Donc, une racine "osm" avec un noeud "bounds" et une liste de noeuds "node", tous avec des attributs.</p>
<h1>Initialisation</h1>
<p>L'initialisation est très simple, et bien expliquée dans les tutoriaux officiels :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p500code2'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p5002"><td class="code" id="p500code2"><pre class="cpp" style="font-family:monospace;">xmlTextReaderPtr reader <span style="color: #000080;">=</span> xmlReaderForFile<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;machin.xml&quot;</span>, <span style="color: #0000ff;">NULL</span>, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>reader <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
<span style="color: #666666;">// 1 if the node was read successfully, 0 if there is no more nodes to read, or -1 in case of error :</span>
<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>xmlTextReaderRead<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
readRoot<span style="color: #008000;">&#40;</span>policy<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// C'est ici qu'on va lire la racine du fichier, et tout les enfants</span>
xmlFreeTextReader<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<h1>Lecture</h1>
<p>Voyons voir cette fonction readRoot :</p>
<p>Tout d'abord, un petit test pour être sûr que l'on a pas fait de bêtise :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p500code3'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p5003"><td class="code" id="p500code3"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>xmlTextReaderDepth<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">return</span> error<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;Le noeud racine devrait être OSM&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Ensuite, on demande au parser le nom de l'élément suivant. Il va donc lire juste ce qu'il faut du fichier pour savoir ça, et s'arrêter :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p500code4'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p5004"><td class="code" id="p500code4"><pre class="cpp" style="font-family:monospace;">xmlChar <span style="color: #000040;">*</span>name<span style="color: #008080;">;</span>
name <span style="color: #000080;">=</span> xmlTextReaderName<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>On vérifie alors qu'on a bien un noeud "osm" comme racine:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p500code5'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p5005"><td class="code" id="p500code5"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>name <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">return</span> error<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;pas de noeud racine&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>xmlStrcmp<span style="color: #008000;">&#40;</span>name, <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> xmlChar <span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span> <span style="color: #FF0000;">&quot;osm&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">return</span> error<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;Ceci n'est pas un fichier OpenStreetMap&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Maintenant qu'on est sûrs qu'on est dans l'élément qu'on veut, on n'a plus besoin de name, donc on le libère :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p500code6'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p5006"><td class="code" id="p500code6"><pre class="cpp" style="font-family:monospace;">xmlFree<span style="color: #008000;">&#40;</span>name<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Ensuite, on va lire tous les attributs, par exemple pour vérifier qu'on est bien en OSM 0.6 :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p500code7'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p5007"><td class="code" id="p500code7"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span>xmlTextReaderMoveToNextAttribute<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span>
    xmlChar <span style="color: #000040;">*</span>name_attrib, <span style="color: #000040;">*</span>value_attrib<span style="color: #008080;">;</span>
    name_attrib <span style="color: #000080;">=</span> xmlTextReaderName<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    value_attrib <span style="color: #000080;">=</span> xmlTextReaderValue<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>xmlStrcmp<span style="color: #008000;">&#40;</span>name_attrib, <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> xmlChar <span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span> <span style="color: #FF0000;">&quot;version&quot;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span><span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span> xmlStrcmp<span style="color: #008000;">&#40;</span>value_attrib, <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> xmlChar <span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span> <span style="color: #FF0000;">&quot;0.6&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span>
        std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;Attention, la version du fichier n'est pas 0.6&quot;</span> <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
    xmlFree<span style="color: #008000;">&#40;</span>name_attrib<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    xmlFree<span style="color: #008000;">&#40;</span>value_attrib<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Remarquez que les attributs ne sont absolument pas ordonnés, ni accessibles tous d'un coup. Si c'est le comportement que vous souhaitez, utilisez une map<string, string> (ou map<string, boost::any> )<br />
On veut maintenant lire les enfants : on demande le chunk suivant, on regarde son type, et on avise. Et on répète jusqu'à ce que le fichier soit vide, càd que xmlTextReaderRead retourne 0 (fin) ou -1 (erreur).</p>
<p>L'astuce, c'est que dans le "on avise", on va également pouvoir appeler xmlTextReaderRead, et lire ainsi récursivement tous les enfants :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p500code8'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p5008"><td class="code" id="p500code8"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span> ret <span style="color: #000080;">=</span> xmlTextReaderRead<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span>ret <span style="color: #000080;">==</span> <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    xmlChar <span style="color: #000040;">*</span> name <span style="color: #000080;">=</span> xmlTextReaderName<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>xmlStrcmp<span style="color: #008000;">&#40;</span>name, <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> xmlChar <span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span> <span style="color: #FF0000;">&quot;bounds&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> ret <span style="color: #000080;">=</span> readBounds<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>xmlStrcmp<span style="color: #008000;">&#40;</span>name, <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> xmlChar <span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span> <span style="color: #FF0000;">&quot;node&quot;</span>  <span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> ret <span style="color: #000080;">=</span> readNode<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>    <span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>xmlStrcmp<span style="color: #008000;">&#40;</span>name, <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> xmlChar <span style="color: #000040;">*</span><span style="color: #008000;">&#41;</span> <span style="color: #FF0000;">&quot;way&quot;</span>   <span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> ret <span style="color: #000080;">=</span> readWay<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span>
    <span style="color: #0000ff;">else</span>                                                  <span style="color: #008000;">&#123;</span> ret <span style="color: #000080;">=</span> xmlTextReaderRead<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span> <span style="color: #666666;">// Ne devrait pas arriver, mais peut-être que le fichier est mal formé ?</span>
    xmlFree<span style="color: #008000;">&#40;</span>name<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Et voilà ! readBounds n'a pas de surprises, il n'y a que des attributs, mais voyons readNode pour l'exemple :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p500code9'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p5009"><td class="code" id="p500code9"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>xmlTextReaderDepth<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">return</span> error<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;un Node doit être au niveau 1&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span>xmlTextReaderMoveToNextAttribute<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span>
    <span style="color: #666666;">// Faites ce que vous voulez avec les attributs</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">int</span> ret <span style="color: #000080;">=</span> xmlTextReaderRead<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span>ret <span style="color: #000080;">==</span> <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
&nbsp;
    <span style="color: #666666;">// un noeud frère ou parent arrive : on redonne le contrôle au parent pour qu'il le gère.</span>
    <span style="color: #666666;">// Si c'est de nouveau un noeud, readRoot rappellera tout naturellement readNode.</span>
	<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>xmlTextReaderDepth<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;=</span> <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span>
		<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span> <span style="color: #666666;">// 1 = lire la suite (cf readRoot)</span>
	<span style="color: #008000;">&#125;</span><span style="color: #0000ff;">else</span><span style="color: #008000;">&#123;</span> <span style="color: #666666;">// child node</span>
	xmlChar <span style="color: #000040;">*</span> name <span style="color: #000080;">=</span> xmlTextReaderName<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #666666;">// faire quelque chose en fonction de name. Ici, on lit en boucle en ignorant les tags</span>
        ret <span style="color: #000080;">=</span> xmlTextReaderRead<span style="color: #008000;">&#40;</span>reader<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        xmlFree<span style="color: #008000;">&#40;</span>name<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> <span style="color: #666666;">// Ne devrait pas arriver</span></pre></td></tr></table></div>

<h1>Lecture de très gros fichiers</h1>
<p>Quand on lit des fichiers de 200Go, il est souvent utile de prévenir l'utilisateur de là où on en est, histoire d'éviter le ctrl-c furieux. On sort alors un peu d'une utilisation "simple" de la libxml2, mais c'est possible.</p>
<p>Tout d'abord, on abandonne xmlReaderForFile au profit de xmlNewTextReader, qui prend en paramètre un xmlParserInputBufferPtr. Cet objet implémentera les callbacks de lecture de fichier (i.e. fopen, fread, etc), tout comme xmlReaderForFile le fait en interne, à la différence près qu'on va retenir là où on en est dans le fichier.</p>
<p>Tout d'abord, on veut trouver la taille du fichier, en octets :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p500code10'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p50010"><td class="code" id="p500code10"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">FILE</span> <span style="color: #000040;">*</span> file <span style="color: #000080;">=</span> <span style="color: #0000dd;">fopen</span><span style="color: #008000;">&#40;</span>path,<span style="color: #FF0000;">&quot;r&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>m_file<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">return</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1</span><span style="color: #008080;">;</span>
 _fseeki64<span style="color: #008000;">&#40;</span>m_file,<span style="color: #0000dd;">0</span>, <span style="color: #0000ff;">SEEK_END</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
 __int64 size <span style="color: #000080;">=</span> _ftelli64<span style="color: #008000;">&#40;</span>m_file<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// la taille</span>
 _fseeki64<span style="color: #008000;">&#40;</span>m_file,<span style="color: #0000dd;">0</span>, <span style="color: #0000ff;">SEEK_SET</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Remarquez que l'on n'utilise pas fseek, qui sont limités à des fichiers de 3Go (adressable en 32 bits). Les streams C++ ont le même problème sur les OS 32 bits, d'où l'utilisation de ces fonction assez incongrues en C++.</p>
<p>Maintenant, créons notre parseur :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p500code11'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p50011"><td class="code" id="p500code11"><pre class="cpp" style="font-family:monospace;">xmlParserInputBufferPtr input <span style="color: #000080;">=</span> xmlParserInputBufferCreateIO<span style="color: #008000;">&#40;</span>
    xmlInputReadCallback_Function,
    xmlInputCloseCallback_Function,
    <span style="color: #0000dd;">this</span>, <span style="color: #666666;">// Ou n'importe quel objet, ou même NULL si vous mettez vos données en global</span>
    XML_CHAR_ENCODING_NONE
 <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
reader <span style="color: #000080;">=</span> xmlNewTextReader<span style="color: #008000;">&#40;</span>input, <span style="color: #FF0000;">&quot;foobar file&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// Le second paramètre est obligatoire et inutile</span></pre></td></tr></table></div>

<p>Nous avons donc besoin de deux fonctions : xmlInputReadCallback_Function et xmlInputCloseCallback_Function. La seconde est assez évidente (fclose), intéressons-nous à la première :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p500code12'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p50012"><td class="code" id="p500code12"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span> xmlInputReadCallback_Function <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">void</span> <span style="color: #000040;">*</span> c, <span style="color: #0000ff;">char</span> <span style="color: #000040;">*</span> buffer, <span style="color: #0000ff;">int</span> length <span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #666666;">// length est la taille du buffer demandé.</span>
    <span style="color: #666666;">// Sauf si vous avez recompilé la lib avec des options particulières, ce sera 4096, soit 4Ko</span>
    UpdateProgress<span style="color: #008000;">&#40;</span>length<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #666666;">// Lit 4096 octets du fichier dans le buffer</span>
    <span style="color: #0000ff;">return</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span><span style="color: #008000;">&#41;</span><span style="color: #0000dd;">fread</span><span style="color: #008000;">&#40;</span>buffer,<span style="color: #0000dd;">1</span>,length,file<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Voilà, le callback est fini. Il ne vous reste plus qu'à implémenter UpdateProgress à votre convenance. Par exemple, pour une application en ligne de commande :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p500code13'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p50013"><td class="code" id="p500code13"><pre class="cpp" style="font-family:monospace;">pos<span style="color: #000040;">+</span><span style="color: #000080;">=</span>length<span style="color: #008080;">;</span> <span style="color: #666666;">// On retient la position actuelle</span>
<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>m_size <span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span><span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span> <span style="color: #008000;">&#40;</span><span style="color: #0000dd;">100</span><span style="color: #000040;">*</span><span style="color: #008000;">&#40;</span>m_pos<span style="color: #000040;">-</span>length<span style="color: #008000;">&#41;</span><span style="color: #000040;">/</span>m_size<span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #0000dd;">100</span><span style="color: #000040;">*</span>m_pos<span style="color: #000040;">/</span>m_size<span style="color: #008000;">&#41;</span> <span style="color: #666666;">// Si la position a changé de plus de 1%</span>
 std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">100</span><span style="color: #000040;">*</span>m_pos<span style="color: #000040;">/</span>m_size<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span> <span style="color: #666666;">// on affiche</span></pre></td></tr></table></div>

<p>ce qui fera un compteur de 1 à 100. Avec Qt, un signal en <tt>Qt::QueuedConnection (pour éviter de bloquer l'UI) fera également très bien l'affaire.<br />
</tt></p>
<h1>Conclusion</h1>
<p>Nous avons donc vu comment lire un très gros fichier XML avec l'API Stax de la libxml2. Maintenant, il ne vous reste plus qu'à encapsuler tout ça, vu que pour des raisons de simplicité, j'ai fait comme si toutes les variables étaient globales.</p>
<p>Donc pour résumer :</p>
<ul>
<li>DOM si vous pouvez</li>
<li>Sax si vous êtes obligés (pas d'autre API sur votre plate-forme, ...)</li>
<li>Stax sinon !</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.coder-studio.com/blog/utilisation-de-lapi-stax-de-libxml2/feed/</wfw:commentRss>
		<slash:comments>1406</slash:comments>
		</item>
		<item>
		<title>Interfacage Assembleur / C++</title>
		<link>http://www.coder-studio.com/blog/interfacage-assembleur-c/</link>
		<comments>http://www.coder-studio.com/blog/interfacage-assembleur-c/#comments</comments>
		<pubDate>Mon, 28 Feb 2011 22:03:59 +0000</pubDate>
		<dc:creator>Calvin1602</dc:creator>
				<category><![CDATA[assembleur]]></category>
		<category><![CDATA[C & C++]]></category>

		<guid isPermaLink="false">http://www.coder-studio.com/blog/?p=493</guid>
		<description><![CDATA[Un autre vieux tuto : comment accéder à vos structures C++ à partir de l'assembleur.]]></description>
			<content:encoded><![CDATA[<p>Un autre vieux tuto : comment accéder à vos structures C++ à partir de l'assembleur.<br />
<span id="more-493"></span></p>
<blockquote><p>C'était mon tout premier tuto <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Une pièce d'histoire...</p></blockquote>
<p>Welcome pour mon premier tuto <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Nous allons apprendre à faire un truc trop cool, de la POO en assembleur.<br />
Mais bon on va y aller doucement, on va commencer par interfacer asm et C.</p>
<p>Pour commencer, quel est l'intérêt ? Tout simplement d'avoir accès à toutes les possibilités de l'assembleur tout en gardant un contrôle total sur le code généré (puisque justement c'est nous qui le générons ^^ ).<br />
Evidement on pourrait simplement mettre asm{ /* code */ } mais le compilo rajoute ses propres trucs, et si on a une application très spéciale ça peut être embêtant ( je pense tout particulièrement à ScalP pour ceux qui connaissent, où j'ai été obligé de faire ça ): on n'a pas de contrôle sur les registres utilisés ainsi que sur l'utilisation de la pile, à laquelle on peut vouloir accéder.<br />
En outre ce n'est absolument pas portable, chaque compilo a sa propre syntaxe.<br />
De toute façon pour les indécis j'ai un argument-choc : ça fait méga g33k!<br />
convaincu ? ^^</p>
<p>Alors allons-y...</p>
<h1>Interfacer assembleur et C</h1>
<h2>Appeler de l'assembleur en C</h2>
<p>Pour ceux qui ne connaissent absolument rien à l'assembleur, un chti tuto est disponible [url="http://www.coder-studio.com/?page=tutoriaux_aff&amp;code=asm_1"]ici[/url], merci Funto !</p>
<p>Disons qu'on a ce programme :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p493code14'); return false;">View Code</a> C</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49314"><td class="code" id="p493code14"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// main.cint asm_carre (int);</span>
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span> <span style="color: #993333;">int</span> nagrs<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span> vargs<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
 <span style="color: #993333;">int</span> a <span style="color: #339933;">=</span> <span style="color: #0000dd;">4</span><span style="color: #339933;">;</span>
 <span style="color: #993333;">int</span> b <span style="color: #339933;">=</span> asm_carre<span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span style="color: #000066;">printf</span></a><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;D'après notre fonction assembleur, le carré de %d vaut %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>a<span style="color: #339933;">,</span>b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>avec int asm_carre (int) une fonction que l'on va implémenter en assembleur.<br />
On écrit le prototype dans le .c pour que le compilateur connaisse la fonction.<br />
Bien évidemment ça ne compilera pas dans l'état, personne ne connaît où se trouve l'implémentation de asm_carre.<br />
Mais où mettre cette implémentation ? simple, dans un .asm... gogogo !</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p493code15'); return false;">View Code</a> ASM</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49315"><td class="code" id="p493code15"><pre class="asm" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">; asm_carre.asm</span>
<span style="color: #009900; font-weight: bold;">&#91;</span>BITS <span style="color: #0000ff;">32</span><span style="color: #009900; font-weight: bold;">&#93;</span>
<span style="color: #000000; font-weight: bold;">segment</span> <span style="color: #000000; font-weight: bold;">.data</span> <span style="color: #666666; font-style: italic;">; données initialisées: rien pour l'instant.</span>
<span style="color: #000000; font-weight: bold;">segment</span> <span style="color: #339933;">.</span>bss  <span style="color: #666666; font-style: italic;">; données non initialisées, toujours rien.</span>
<span style="color: #000000; font-weight: bold;">segment</span> <span style="color: #339933;">.</span>text <span style="color: #666666; font-style: italic;">; ah ! on entre dans le CS ( Code Segment )</span>
 global _asm_carre <span style="color: #666666; font-style: italic;">; on va exporter ce symbole</span>
_asm_carre<span style="color: #339933;">:</span>
 <span style="color: #00007f; font-weight: bold;">enter</span> <span style="color: #0000ff;">0</span><span style="color: #339933;">,</span><span style="color: #0000ff;">0</span>         <span style="color: #666666; font-style: italic;">; on n'utilise aucune variable, uniquement des registes.</span>
 <span style="color: #00007f; font-weight: bold;">push</span> <span style="color: #00007f;">ebx</span>          <span style="color: #666666; font-style: italic;">; La valeur de ebx ne DOIT PAS être modifiée par la fonction !! alors on le met temporairement sur la pile ( même si dans ce cas précis c'est inutile )</span>
 <span style="color: #00007f; font-weight: bold;">mov</span> <span style="color: #00007f;">eax</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">&#91;</span><span style="color: #00007f;">ebp</span><span style="color: #339933;">+</span><span style="color: #0000ff;">8</span><span style="color: #009900; font-weight: bold;">&#93;</span>   <span style="color: #666666; font-style: italic;">; le paramètre de la fonction ce trouve à cet endroit.</span>
 <span style="color: #00007f; font-weight: bold;">mul</span> <span style="color: #00007f;">eax</span>           <span style="color: #666666; font-style: italic;">; eax = a*a</span>
 <span style="color: #00007f; font-weight: bold;">pop</span> <span style="color: #00007f;">ebx</span>           <span style="color: #666666; font-style: italic;">; on restaure ebx</span>
 <span style="color: #00007f; font-weight: bold;">leave</span>             <span style="color: #666666; font-style: italic;">;</span>
 <span style="color: #00007f; font-weight: bold;">ret</span>               <span style="color: #666666; font-style: italic;">; retour à la fonction appelante</span></pre></td></tr></table></div>

<p>héé partez pas <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_lol.gif' alt=':lol:' class='wp-smiley' /><br />
Pour les quatre premières lignes, si vous ne comprenez pas refaites un petit tour sur le tuto de Funto.<br />
bon.<br />
pourquoi global?  pour dire à NASM que cette fonction pourra être appelée d'un programme externe.<br />
pourquoi _asm_carre et non pas asm_carre ? C'est une convention d'écriture. Chaque fois que vous voudrez créer une fonction asm devant être appelée à partir du C, il faudra préfixer le label par _</p>
<p>ensuite place à l'implémentation.<br />
Attention, rappelez vous que la pile de processeur commence à DROITE et s'aggrandit vers la gauche, donc quand on pushe une variable, elle se met le plus à gauche possible. Du coup ce qui se trouve en ebp+4 a été mis sur la pile AVANT ce qui se trouve en ebp+0</p>
<p>enter 0,0 : ne sert pas à grand chose ici.</p>
<p>push ebx : ici cela n'est pas réellement utile non plus puisque ebx, on n'y touche pas; mais c'est une question de bonnes habitudes car il est interdit pour une fonction de modifier ebx ( quand on l'interface avec du C/C++ tout du moins, en asm pur vous faites ce que vous voulez )<br />
C'est embêtant ça ! déjà que des registes on n'en a pas beaucoup... alors du coup on le pushe, et on le popera juste avant de redonner la main au C.<br />
à vrai dire.. il n'y a pas que ebx, mais aussi esi,edi,ebp,cs,ds,ss et es ... au pire : pusha / popa.<br />
]</p>
<pre>----------------------------------------------------------------
| adresse ||| ebp - 4  | ebp + 0  |    ebp + 4     |  ebp + 8  |
----------------------------------------------------------------
| contenu |||   ???    |    ebp   | adresse retour | parametre |
----------------------------------------------------------------</pre>
<p>mov eax,[ebp+8] : strico sensu, met ce qui se trouve en ebp+8 ( sur la pile ) dans eax. Mais qu'est-ce qui se trouve donc en ebx+8 ? ohhh, notre paramètre <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>mul eax,eax : on multiplie eax par lui même ...</p>
<p>pop ebx: voilà, comme ça le standard est respecté et on risque pas de se retrouver avec erreurs incompréhensibles.</p>
<p>leave: symétrique de enter</p>
<p>ret : pope l'adresse de la fonction appelante et y va: ici, on était dans le main, ligne 2...</p>
<p>et voilà nous revoilà dans notre programme C avec le carré du paramètre dans eax. cool, ça sert à quoi? hé bien justement, la valeur de retour d'une fonction DOIT être dans eax, c'est la règle. Et du coup, tout est bon, b=a^2.</p>
<p>En fait on pouvait faire plus simple, c'est là tout l'avantage de l'assembleur :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p493code16'); return false;">View Code</a> ASM</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49316"><td class="code" id="p493code16"><pre class="asm" style="font-family:monospace;">_asm_carre<span style="color: #339933;">:</span>
 <span style="color: #00007f; font-weight: bold;">mov</span> <span style="color: #00007f;">eax</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">&#91;</span><span style="color: #00007f;">esp</span><span style="color: #339933;">+</span><span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#93;</span>
 <span style="color: #00007f; font-weight: bold;">mul</span> <span style="color: #00007f;">eax</span>
 <span style="color: #00007f; font-weight: bold;">ret</span></pre></td></tr></table></div>

<p>fini ! La rule of thumb, c'est 1 : vous ne modifiez pas les registres cités plus haut et 2 : valeur de retour dans eax.<br />
[nota : eax c'est pour les DWORDS. Pour un WORD c'est ax, pour un QWORD, edx:eax]<br />
remarquez que je n'ai pas utilisé ebp (base pointer) mais esp ( stack pointer ) car il n'y a pas la commande enter, dont l'un des rôle est justement de faire mov ebp,esp.</p>
<p>Bon , compilons ! OK c'est bon ça marche... Argheul nan, la compilation se fait sans ennuis mais erreur au linkage : l'éditeur de liens ne sait pas où trouver l'implémentation de asm_carre. Et pour cause ! il n'a pas été assemblé :niii:<br />
Qu'à cela ne tienne :</p>
<pre>C:\&gt;nasm.exe -o asmlib.o -f coff asm_carre.asm</pre>
<p>( si vous n'êtes pas sous windows utilisez -f elf )<br />
Voilà vous avez un merveilleux .o ! Il n'y a plus qu'à demander au compilo de linker avec , et magie !! ça plante <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /><br />
[NOTAs :</p>
<ul>
<li>on peut utiliser aussi, nasm -f win32 asm_carre.asm , ca donnera asm_carre.obj, à linker de même manière.</li>
<li>Pour éviter de retourner dans la console à chaque modif on peut aussi faire ça automatiquement : dans VC6, Project-&gt;Settings-&gt; onglet pre-link step-&gt; nouveau-&gt; entrez cette ligne...</li>
</ul>
<p>]</p>
<p>( bon en fait non ça plante pas mais c'est parce que vous avez de la chance )<br />
La raison est simple, la convention d'appel utilisée par le compilo C++ est le _stdcall ( params empilés de gauche à droite, dépilés dans la fonction elle même ) et il y a de fortes chances pour que vous ayez écrit votre fonction assembleur en _cdecl ( params empilés de droite à gauche, dépilés par le programme appelant ). Aurement dit, gros plantage assuré s'il n'y a pas la même convention des deux côtés (heureusement ici c'est du C, pas du C++, donc pas de plantage en fait) .<br />
pour spécifer la convention :</p>
<ul>
<li> sous VC++ : _cdecl int fonction ( int );  //  respectivement _stdcall</li>
<li>sous GCC  : int fonction ( int ) __attribute__((cdecl)); // respectivement stdcall</li>
</ul>
<p>Yeah ! Là ça marche vraiment, et on sait pourquoi <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h2>Appeler de l'asm, qui appelle du C</h2>
<p>Bon, on ne va pas s'arrêter en si bon chemin ... maintenant qu'on sait écrire des fonctions hyper puissantes et polyvalentes en assembleur ( *hum* ), on aura sûrement besoin, à un moment ou à un autre, d'appeller une fonction qui elle est implémentée dans le prog C, ou même dans les librairies standard ... genre strcmp !</p>
<p>Pour ça c'est très simple, il suffit de déclarer le nom de la fonction en extern au début du segment .text et le linker s'occupera de tout.</p>
<p>Dans le genre "Programme qui sert à rien" ça donne ça:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p493code17'); return false;">View Code</a> C</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49317"><td class="code" id="p493code17"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// main.c</span>
<span style="color: #993333;">int</span> _cdecl asm_carre <span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span> <span style="color: #993333;">int</span> nagrs<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">**</span> vargs<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
 <span style="color: #993333;">int</span> a <span style="color: #339933;">=</span> <span style="color: #0000dd;">4</span><span style="color: #339933;">;</span>
 <span style="color: #993333;">int</span> b <span style="color: #339933;">=</span> asm_carre<span style="color: #009900;">&#40;</span>a<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span style="color: #000066;">printf</span></a><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;D'après notre fonction assembleur, le carré de %d vaut %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>a<span style="color: #339933;">,</span>b<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #993333;">int</span> _cdecl carre<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> a<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><span style="color: #b1b100;">return</span> a<span style="color: #339933;">*</span>a<span style="color: #339933;">;</span><span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>puis:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p493code18'); return false;">View Code</a> ASM</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49318"><td class="code" id="p493code18"><pre class="asm" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">; asm_carre.asm</span>
<span style="color: #009900; font-weight: bold;">&#91;</span>BITS <span style="color: #0000ff;">32</span><span style="color: #009900; font-weight: bold;">&#93;</span>
<span style="color: #000000; font-weight: bold;">segment</span> <span style="color: #339933;">.</span>text
 global _asm_c_carre<span style="color: #339933;">:</span>
 <span style="color: #000000; font-weight: bold;">extern</span> _carre <span style="color: #666666; font-style: italic;">;remarquez qu'ici aussi on met un _</span>
_asm_c_carre<span style="color: #339933;">:</span>
 <span style="color: #00007f; font-weight: bold;">mov</span> <span style="color: #00007f;">eax</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">&#91;</span><span style="color: #00007f;">esp</span><span style="color: #339933;">+</span><span style="color: #0000ff;">4</span><span style="color: #009900; font-weight: bold;">&#93;</span>   <span style="color: #666666; font-style: italic;">; on prend le param sur la pile</span>
 <span style="color: #00007f; font-weight: bold;">push</span> <span style="color: #00007f;">eax</span>      <span style="color: #666666; font-style: italic;">; on le re-pushe au sommet de la pile</span>
 <span style="color: #00007f; font-weight: bold;">call</span> _carre      <span style="color: #666666; font-style: italic;">; on appelle la fonction</span>
 <span style="color: #00007f; font-weight: bold;">add</span> <span style="color: #00007f;">esp</span><span style="color: #339933;">,</span><span style="color: #0000ff;">4</span>         <span style="color: #666666; font-style: italic;">; on dépile</span>
 <span style="color: #00007f; font-weight: bold;">ret</span>               <span style="color: #666666; font-style: italic;">; on retourne au C</span></pre></td></tr></table></div>

<p>Héé oui vous l'aurez compris, ce code atteint le sommum de l'inutilité en appellant la fonction asm_carre qui se contente d'appeler carre(), qui lui est implémenté en C ^^<br />
Attention cependant, cela ne marche pas avec le format COFF, le win32 est impératif ( et souvenez vous que du coup ça donne pas en .o mais un .obj)</p>
<h1>Interfacer assembleur et C++</h1>
<p>- Here comes the bidouille -</p>
<p>Bien, toutes les bases sont posées, ce que vous ferez de cela dépendra de vos connaissances en assembleur.<br />
Mais maintenant nous sommes en 2006, ya un truc qui est pas mal : le C++.<br />
ça serait bien qu'on puisse interfacer le C++ et l'assembleur de la même manière qu'avec le C... non?</p>
<p>Malheureusement la convention qui nous dit de rajouter un petit _ , c'est une convention C ! et non C++ ...<br />
c'est là que les embrouilles commencent, parce que les éditeurs de compilateurs s'en sont donné à coeur joie pour nous peaufiner des tonnes de conventions aussi différentes et incompréhensibles les unes que les autres...<br />
ça s'appelle le name mangling ( décoration de nom ) et c'est pas du tout, mais alors pas du tout standardisé.<br />
Heureusement, le linker est votre ami !<br />
Ainsi, si vous renommez le main.c précédent en main.cpp, la compilation encore une fois se déroulera sans souci, mais le linker va vous sortir une erreur du genre :</p>
<pre>tuto.obj : error LNK2001: unresolved external symbol "int __cdecl asm_carre(int)" (?asm_carre@@YAHH@Z)</pre>
<p>Oh magie , un joli nom de label tout bizarroïde apparaît : ?asm_carre@@YAHH@Z<br />
Il suffit d'un petit copier-coller de ce nom pour remplacer tous les _asm_carre par ?asm_carre@@YAHH@Z dans le listing assembleur.<br />
On réassemble, on recompile, ça marche ! *joie*</p>
<p>Pour la compatibilité entre les différents compilateurs, on peut s'amuser à regarder toutes les erreurs de linkage créées par tous ces compilos, ajouter tous ces noms dans la liste des labels extern, et remplacer chaqun de ces labels par la liste des labels demandés par l'ensemble des compilos.....</p>
<h2>Assembleur Orienté Objet ?</h2>
<p>Oui c'est possible <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Tout du moins à certaines conditions .....<br />
Admettons que nous ayons une classe CMaClasse avec une fonction membre void Calcule(void).<br />
hé bien jusque là c'est très simple : c'est exactement la même chose qu'avant. On regarde l'erreur du linker, on copie-colle le nom de la fonction.<br />
Ca marche ... si et seulement si ladite classe est un POD ou au mieux un agrégat. Donc : pas de virtuel ! ni fonction ni membre ni quoi que ce soit de virtuel. On a le droit à l'héritage si ça reste un agrégat, mais bon ça devient plus compliqué après et à priori ça dépend du compilo utilisé.<br />
( théoriquement, même avec du virtuel c'est possible mais n'y songez même pas ^^)</p>
<p>Bon , maintenant, admettons que l'on veuille prendre des paramètres. le prototype devient:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p493code19'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49319"><td class="code" id="p493code19"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> CMaCLasse<span style="color: #008080;">::</span><span style="color: #007788;">Calcule</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> a<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>sauf que ...<br />
sauf que c'est pas si simple, ce prototye c'est celui que vous écrivez, pas celui qui est utilisé.<br />
le compilo, lui, il comprend ça:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p493code20'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49320"><td class="code" id="p493code20"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> CMaClasse<span style="color: #008080;">::</span><span style="color: #007788;">Calcule</span><span style="color: #008000;">&#40;</span> CMaClasse<span style="color: #000040;">*</span> <span style="color: #0000dd;">this</span>, <span style="color: #0000ff;">int</span> a<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>c'est d'ailleurs pour ça que vous avez accès aux membres quand vous faites Instance-&gt;fonction();, ça tombe pas du ciel ...</p>
<p>Une fois dans la partie asm, voilà donc l'état de la pile:</p>
<pre>----------------------------------------------------------------------------
| adresse ||| ebp - 4  | ebp + 0  |    ebp + 4     |  ebp + 8  | ebp + 12  |
----------------------------------------------------------------------------
| contenu |||   ???    |    ebp   | adresse retour |    this   | parametre |
----------------------------------------------------------------------------</pre>
<p>'a' n'est donc plus en ebp+8 mais en ebp+12 ! à part ça rien ne change.</p>
<p>bon , maintenant que j'ai accès aux paramètres, je veux une valeur de retour: pareil qu'en C ! dans eax ...</p>
<p>[NOTA : dans la source d'exemple , j'accède à this avec mov ecx,[esp+4], mais c'est parce que je n'utilise pas enter et leave.</p>
<p>et dernier point fun : accéder aux membres <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Le truc sympa c'est qu'on a this...<br />
ce qu'il faudrait c'est donc ça : (ebp+8)-&gt;_membre, c'est à dire, en simili-nasm: [ebp+8]._membre<br />
mais comment avoir l'adresse de _membre ? simple, pour un POD, le c++ demande que les membres soient stockés en mémoire de façon contigüe (cela est rarement respecté, voir plus bas) et dans l'ordre de la déclaration.<br />
exemple:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p493code21'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49321"><td class="code" id="p493code21"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> CMaClasse<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
 <span style="color: #0000ff;">int</span> a<span style="color: #008080;">;</span>
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
 <span style="color: #0000ff;">char</span> c<span style="color: #008080;">;</span>
<span style="color: #0000ff;">protected</span><span style="color: #008080;">:</span>
 <span style="color: #0000ff;">float</span> f<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
CMaClasse inst<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>dans ce cas, la mémoire sera :</p>
<pre>0         4   5         9
-------------------------
| * * * * | * | * * * * |
|    a    | c |    f    |
-------------------------</pre>
<p>( un * correspond un octet, le 4 signifie qu'on se situe à l'adresse &amp;inst +4 )<br />
( On voit d'ailleurs qu'il est presque toujours préférable de classer ses membres par taille décroissante, ça optimise les accès mémoire)</p>
<p>NOTA:<br />
la plupart des compilos alignent automatiquement sur 4 octets (c'est plus rapide à l'exec), ce qui donne une organisation de la mémoire comme ça:</p>
<pre>0         4        8         12
------------------------------
| * * * * | *      | * * * * |
|    a    | c      |    f    |
------------------------------</pre>
<p>on peu configurer ça soi même l'alignement mémoire avec la directive pragma.<br />
Pour comprimer au maximum la structure sous VC++ :</p>
<pre lang=C" >#pragma pack(push)
#pragma pack(1)
struct lkjlkj{...};
#pragma pack(pop)</pre>
<p>et sous gcc:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p493code22'); return false;">View Code</a> C</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49322"><td class="code" id="p493code22"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">struct</span> ljhlkjh<span style="color: #009900;">&#123;</span>
...
<span style="color: #009900;">&#125;</span>__attribute__<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>packed<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// (oui c'est compliqué et alors ? :p)</span></pre></td></tr></table></div>

<p>/NOTA</p>
<p>nous disions donc que nous avions this en ebp+8 et qu'on voulait les membres... admettons que je veuille mettre f dans ebx. je dois alors faire:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p493code23'); return false;">View Code</a> ASM</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49323"><td class="code" id="p493code23"><pre class="asm" style="font-family:monospace;"><span style="color: #00007f; font-weight: bold;">mov</span> <span style="color: #00007f;">ecx</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">&#91;</span><span style="color: #00007f;">ebp</span><span style="color: #339933;">+</span><span style="color: #0000ff;">8</span><span style="color: #009900; font-weight: bold;">&#93;</span> <span style="color: #666666; font-style: italic;">;ecx=this;</span>
<span style="color: #00007f; font-weight: bold;">mov</span> <span style="color: #00007f;">eax</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">&#91;</span><span style="color: #00007f;">ecx</span><span style="color: #339933;">+</span><span style="color: #0000ff;">5</span><span style="color: #009900; font-weight: bold;">&#93;</span> <span style="color: #666666; font-style: italic;">;eax=*(this+5); on met dans eax les 4 octets( 4 car c'est eaXX) situés à l'adresse this+5</span></pre></td></tr></table></div>

<p>(on peut optimiser avec lea , mais passons)<br />
à partir de là on peut accéder au membres, une bonne idée est d'utiliser les macros de nasm pour y accéder plus aisément en donnant des noms compréhensibles a [ecx+5] ...)</p>
<p>voili voilou !!!<br />
Comment ça ya plus personne avec moi :p</p>
<p>dernière chose: Magie de l'assembleur on peut même appeller des fonctions membres...mais fait connaître le label, pour ça il suffit de faire un appel de ladite fonction quelque part dans le c++ tout en commentant l'implémentation. Le linker va râler, et par là même donner le label qu'il cherche.<br />
Ne pas oublier de pusher this! ...<br />
Maintenant, petit truc sympa et bien utile: quand votre routine asm plante... mettez vous en mode débug dans VC++, relancez...vous verrez s'afficher le desassembly MASM de votre code NASM, avec la ligne à laquelle ça a planté...faites clic droit sur la barre des menus, cliquez sur registres: voilà, vous contrôlez votre machine B-) :p</p>
<p>Bon ben voilà, je verrai ce qu'il y a à ajouter à cela, please feel free de faire des commentaires dans le forum <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
N'oubliez pas d'aller voir les exemples.</p>
<p>Un zip est disponible [url="http://coder-studio.com/tutoriaux/asm/asm_4.zip"]ici[/url], et la discussion se poursuit [url="http://www.coder-studio.com/forum2/viewtopic.php?id=904"]là[/url] !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coder-studio.com/blog/interfacage-assembleur-c/feed/</wfw:commentRss>
		<slash:comments>1391</slash:comments>
		</item>
		<item>
		<title>Tuto OpenGL : les FBO</title>
		<link>http://www.coder-studio.com/blog/tuto-opengl-les-fbo/</link>
		<comments>http://www.coder-studio.com/blog/tuto-opengl-les-fbo/#comments</comments>
		<pubDate>Mon, 28 Feb 2011 22:03:52 +0000</pubDate>
		<dc:creator>Calvin1602</dc:creator>
				<category><![CDATA[OpenGL]]></category>

		<guid isPermaLink="false">http://www.coder-studio.com/blog/?p=490</guid>
		<description><![CDATA[Ceci est du réchauffage micro-ondes d'un vieux tuto sur les FrameBuffer Objects d'OpenGL, qui avait sauté lors du passage à WordPress.]]></description>
			<content:encoded><![CDATA[<p>Ceci est du réchauffage micro-ondes d'un vieux tuto qui avait sauté lors du passage à WordPress.<br />
<span id="more-490"></span></p>
<h1>Introduction</h1>
<p>Ce tutorial s'inscrit dans la lignée du tutorial sur les pbuffers, disponible [url="http://www.coder-studio.com/"]ici[/url] (NDLR : que je n'ai pas reporté tellement c'est vieux).<br />
Le but est toujours le même : permettre d'enregistrer une scène sur une texture rapidement, afin de pouvoir réaliser moult joulis gfx <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /><br />
Nous avions vu que si les pbuffers étaient performants, ils n'existaient que sous Linux. Une extension plus récente a depuis fait apparition, ce sont les framebuffer objets. L'API pour y accéder a été normalisée par l'ARB mi-2004. C'est une extension complexe, la spec fait un demi-Mo de texte brut. Mais n'ayez pas peur, ça va bien se passer <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Une caractéristique agréable du fbo est qu'elle permet, si toutefois la carte graphique le supporte, de dessiner sur des NPOTS : Non Power Of Two textures. Autrement dit, si votre écran fait 800*600, vous pouvez sans problème aucun avoir une texture de 800*600, dessiner dessus, puis l'utiliser comme une texture normale, au lieu de devoir utiliser une 1024x1024 et d'en perdre une bonne partie.</p>
<p>Nous allons donc voir comment utiliser ces textures rectangulaires, puis comment utiliser les fbos.</p>
<h1>Les textures rectangulaires</h1>
<p>Il s'agit ni plus ni moins d'une texture normale, très banale. La seule différence avec GL_TEXTURE_2D est son nom : GL_TEXTURE_RECTANGLE_ARB.<br />
Sans plus attendre, voiçi un exemple complet de création d'une texture vide.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p490code24'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49024"><td class="code" id="p490code24"><pre class="cpp" style="font-family:monospace;">	glEnable<span style="color: #008000;">&#40;</span>GL_TEXTURE_RECTANGLE_ARB<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">int</span> taille_max<span style="color: #008080;">;</span>
	glGetIntegerv<span style="color: #008000;">&#40;</span>GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB,<span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span>taille_max<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot; Taille max de texture supportée : &quot;</span> <span style="color: #000080;">&lt;&lt;</span> taille_max <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
	GLuint rect_tex<span style="color: #008080;">;</span>
	glGenTextures<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span>,<span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span>rect_tex<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	glBindTexture<span style="color: #008000;">&#40;</span>GL_TEXTURE_RECTANGLE_ARB,rect_tex<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// Exactement comme pour les tex2D</span>
	glTexImage2D<span style="color: #008000;">&#40;</span>GL_TEXTURE_RECTANGLE_ARB, <span style="color: #0000dd;">0</span>, GL_RGB8, <span style="color: #0000dd;">800</span>, <span style="color: #0000dd;">600</span>, <span style="color: #0000dd;">0</span>, GL_RGB, GL_INT, <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	glTexParameteri<span style="color: #008000;">&#40;</span>GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	glTexParameteri<span style="color: #008000;">&#40;</span>GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	glTexParameteri<span style="color: #008000;">&#40;</span>GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	glTexParameteri<span style="color: #008000;">&#40;</span>GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Avant de continuer, quelques remarques nécessaires sur les NPOTS.<br />
Il est impossible de créer des mipmaps. Ainsi, il ne faut jamais appeller glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST); ou assimilé.<br />
Elles ne supportent que ces modes de filtrage: GL_CLAMP, GL_CLAMP_TO_EDGE, and GL_CLAMP_TO_BORDER.<br />
Elles ne peuvent avoir de bordure, mais franchement, ce n'est pas bien grave.<br />
Il y a des priorités dans les types de textures. De la moins forte à la plus forte: GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP. Autrement dit: impérativement désactiver les tex3D et les cubemaps avant d'utiliser les texRect !!!<br />
Les texRect sont répandues. Mais pour bien tester leur présence sur la CG, utiliser glGetBooleanv(GL_TEXTURE_RECTANGLE_ARB, &amp;rect_supported);<br />
Plus important ( vital ! )<br />
Les coordonnées de textures ne sont pas normalisées de 0 à 1, mais de 0 à height et de 0 à width.<br />
Pensez-y !</p>
<p>Enfin, c'est une très mauvaise idée d'abandonner subitement les POTS. Elles sont énormément plus rapides, et bénéficient en plus du mipmapping, le gain de vitesse est monstueux. Les NPOTS sont à réserver aux cas particuliers.</p>
<p>Voilà, il n'y a plus grand chose à dire pour une utilisation conventionnelle des textures rectangulaires. Mais il y a bien d'autres surprises, par exemple si vous voulez les utilisez pour les shaders.</p>
<h1>Les Frambuffer Object</h1>
<p>Il est IMPERATIF de tester si la carte supporte cette extension. Même si en 2011, les cartes qui ne la supportent pas sont tellement vieilles que vous feriez mieux d'abandonner tout support technique pour les dinosaures qui en auraient encore une.</p>
<p>Le test est relativement simple:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p490code25'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49025"><td class="code" id="p490code25"><pre class="cpp" style="font-family:monospace;">GLenum status<span style="color: #008080;">;</span>
status <span style="color: #000080;">=</span> glCheckFramebufferStatusEXT<span style="color: #008000;">&#40;</span>GL_FRAMEBUFFER_EXT<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
status<span style="color: #000080;">==</span>GL_FRAMEBUFFER_COMPLETE_EXT<span style="color: #008080;">?</span>
	std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;fbo supporté<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #008080;">:</span>
	std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;fbo non supporté<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>(N'oubliez pas d'initialiser glew au préalable)<br />
Si c'est bon, on peut alors en créer un.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p490code26'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49026"><td class="code" id="p490code26"><pre class="cpp" style="font-family:monospace;">GLuint fbo<span style="color: #008080;">;</span>
glGenFramebuffersEXT<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span>, <span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span>fbo<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
glBindFramebufferEXT<span style="color: #008000;">&#40;</span>GL_FRAMEBUFFER_EXT, fbo<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
glFramebufferTexture2DEXT<span style="color: #008000;">&#40;</span>GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_RECTANGLE_ARB, rect_tex, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Vous remarquerez que, là encore, l'accès aux fonctionnalités d'openGL se fait via des integers, exactement de la même manière que les textures.<br />
C'est peut-être un peu abstrait à manipuler au départ, mais je vous assure que l'on s'y fait vite.<br />
D'ailleurs l'API elle-même est très similaire: glGenFrameBufferEXT, glBindFramebufferEXT... mis à part le Framebuffer et le EXT indiquant que cela ne fait pas partie de l'openGL de base, on ne se sent pas perdus.<br />
La dernière ligne sert à dire que je dessinerai dans le framebuffer, ce sera en réalité dans la texture spécifiée.<br />
Le premier paramètre est obligatoirement GL_FRAMEBUFFER_EXT, aussi stupide que cela _puisse_ paraître.<br />
Le deuxième est GL_DEPTH_ATTACHMENT_EXT pour avoir accès au depth buffer, ou GL_COLOR_ATTACHMENT0_EXT pour la couleur normale.<br />
le 3ème est le type de texture, GL_TEXTURE_2D ou GL_TEXTURE_RECTANGLE_ARB.<br />
Le 4ème l'indice de la texture à utiliser.<br />
Le dernier, enfin, détermine le niveau de mipmap dans lequel effectuer le dessin. Comme les textures rectangulaires ne permettent pas le mipmapping, ce sera forcément 0.</p>
<p>On va mainenant dessiner dans le fbo.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p490code27'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49027"><td class="code" id="p490code27"><pre class="cpp" style="font-family:monospace;">	glEnable<span style="color: #008000;">&#40;</span>GL_TEXTURE_RECTANGLE_ARB<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	glBindFramebufferEXT<span style="color: #008000;">&#40;</span>GL_FRAMEBUFFER_EXT, fbo<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	glDisable<span style="color: #008000;">&#40;</span>GL_TEXTURE_RECTANGLE_ARB<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	glEnable<span style="color: #008000;">&#40;</span>GL_TEXTURE_2D<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #666666;">// Dessin</span></pre></td></tr></table></div>

<p>On remarque qu'il est nécessaire que le type de texture utilisé par le fbo soit activé durant sa propre activation, mais après, on n'en a plus besoin. Il est même important de désactiver les textures rectangulaires, car sinon, comme précisé plus haut, ce paramètre aura précédence sur gl_texture_2d.</p>
<p>On va maintenant dessiner sur l'écran, avec notre texture toute neuve</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p490code28'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p49028"><td class="code" id="p490code28"><pre class="cpp" style="font-family:monospace;">	glBindFramebufferEXT<span style="color: #008000;">&#40;</span>GL_FRAMEBUFFER_EXT, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// cela dessine dans le buffer normal, c'est à dire l'écran.</span>
	<span style="color: #666666;">// Un dessin...</span>
	glBindTexture<span style="color: #008000;">&#40;</span>GL_TEXTURE_RECTANGLE_ARB,rect_tex<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #666666;">// un autre dessin, texturé avec cette texture-ci.</span>
	<span style="color: #666666;">// rappellez vous que les bornes sont [0..w] et [0..h] et non [0..1] !</span></pre></td></tr></table></div>

<p>Voilà ! rien de plus simple, n'est-ce pas ? <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
N'oubliez pas de fermer la porte en partant : 	glDeleteFramebuffersEXT(1, &amp;fbo);<br />
Nous sommes entre gentlemen, après tout.</p>
<h1>Conclusion</h1>
<p>Voici donc une autre méthode pour dessiner dans une texture. J'ai ai profité pour présenter ici les textures rectangulaires, car la plupart des effets nécessitant cette méthode ( ou une équivalente ) sont utilisés pour afficher cette texture en plein écran. Une POT n'est donc pas très appropriée.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coder-studio.com/blog/tuto-opengl-les-fbo/feed/</wfw:commentRss>
		<slash:comments>1084</slash:comments>
		</item>
		<item>
		<title>Tutoriel Boost Graph Library</title>
		<link>http://www.coder-studio.com/blog/tutoriel-boost-graph-library/</link>
		<comments>http://www.coder-studio.com/blog/tutoriel-boost-graph-library/#comments</comments>
		<pubDate>Fri, 25 Sep 2009 01:06:58 +0000</pubDate>
		<dc:creator>Calvin1602</dc:creator>
				<category><![CDATA[C & C++]]></category>
		<category><![CDATA[boost]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[graphes]]></category>
		<category><![CDATA[tutoriel]]></category>

		<guid isPermaLink="false">http://www.coder-studio.com/blog/?p=429</guid>
		<description><![CDATA[Boost, c'est le bien, et la BGL ne fait pas exception à la règle. BGL permet d'utiliser des algorithmes de graphes précodés en l'adaptant à nos besoins via les templates, et économise beaucoup de temps de développement et de debug.
C'est bien beau, mais encore faut-il que les puissants concepts utilisés pour faire fonctionner la librairie soient bien documentés. Or, la documentation de la BGL est tout simplement ignoble [...]
Ce tuto ci se veut simple. Il présente une des milliers de façons de procéder, que je considère comme simple, lisible et maintenable.]]></description>
			<content:encoded><![CDATA[<p>Boost, c'est le bien, et la BGL ne fait pas exception à la règle. BGL permet d'utiliser des algorithmes de graphes précodés en l'adaptant à nos besoins via les templates, et économise beaucoup de temps de développement et de debug.<br />
C'est bien beau, mais encore faut-il que les puissants concepts utilisés pour faire fonctionner la librairie soient bien documentés. Or, la documentation de la BGL est tout simplement ignoble :<br />
<span id="more-429"></span></p>
<ul>
<li>Elle est très peu connexe. Par exemple, il y a un unique lien vers la table des matières.</li>
<li>Elle est peu explicite. Par exemple, dans l'interface de l'algorithme de dijkstra, on peut trouver un bgl_named_parameters. Il faut se lever de bonne heure pour trouver ce que c'est.</li>
<li>Les exemples sont rares et peu explicites. Le seul exemple de l'algorithme A* est peu commenté (et encore moins aux parties les plus dures), démontre deux autres features qui n'ont rien à voir, utilise l'interface obsolète et non recommandée de la lib, et complique le tout avec une autre couche de templates totalement inutile pour un tuto qui se veut simple.</li>
</ul>
<p>Ce tuto ci se veut simple. Il présente une des milliers de façons de procéder, que je considère comme simple, lisible et maintenable. Tous les membres du namespace boost seront préfixés par boost:: afin de savoir qu'est-ce qui est à nous et qu'est-ce qui est à Boost.</p>
<p>Il est basé sur le cas suivant : on a un graphe de waypoints, et on veut utiliser l'algorithme A* (qui utilise une bonne partie des concepts importants de la lib). Dans un premier temps, dans un souci de simplicité, on va utiliser une heuristique par défaut, qui rend toujours zéro. On verra par la suite comment l'adapter.</p>
<p>On va avoir besoin de deux headers boost:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p429code29'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42929"><td class="code" id="p429code29"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;boost/graph/adjacency_list.hpp&gt;</span>
<span style="color: #339900;">#include &lt;boost/graph/astar_search.hpp&gt;</span></pre></td></tr></table></div>

<p>On va maintenant définir les structures nécessaires à définir notre graphe :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p429code30'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42930"><td class="code" id="p429code30"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// Un waypoint</span>
<span style="color: #0000ff;">struct</span> WayPoint<span style="color: #008000;">&#123;</span>
    Vector3f pos<span style="color: #008080;">;</span>
    <span style="color: #666666;">// et éventuellement d'autres informations (crouch, hide, camp, ...)</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #666666;">// Une liaison entre deux waypoints</span>
<span style="color: #0000ff;">struct</span> WayPointConnection<span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">float</span> dist<span style="color: #008080;">;</span>
    <span style="color: #666666;">// idem</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>On va maintenant déclarer le type de notre graphe. On va utiliser une adjacency_list, qui est un peu un graphe à tout faire. Ce n'est pas le plus optimisé dans tous les cas, mais il est très versatile et convient très bien ici.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p429code31'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42931"><td class="code" id="p429code31"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">typedef</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">adjacency_list</span><span style="color: #000080;">&lt;</span>  <span style="color: #666666;">// adjacency_list est un template qui dépend de :</span>
    boost<span style="color: #008080;">::</span><span style="color: #007788;">listS</span>,               <span style="color: #666666;">//  le conteneur utilisé pour les arcs partant d'un sommet. Ici, std::list.</span>
    boost<span style="color: #008080;">::</span><span style="color: #007788;">vecS</span>,                <span style="color: #666666;">//  le conteneur utilisé pour contenir tous les sommets du graphe. Ici, std::vector.</span>
    boost<span style="color: #008080;">::</span><span style="color: #007788;">undirectedS</span>,         <span style="color: #666666;">//  le type des arcs. Pourrait être boost::directedS.</span>
    WayPoint,                   <span style="color: #666666;">//  le type qui décrit un sommet.</span>
    WayPointConnection          <span style="color: #666666;">//  le type qui décrit un arc.</span>
<span style="color: #000080;">&gt;</span> WayPointGraph<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Les deux premiers paramètres influent grandement sur l'organisation mémoire et les performances de graphe. Selon les applications, une liste, un vecteur, un set, une map, ... sera plus approprié. Pour plus d'information, voir <a href="http://www.boost.org/doc/libs/1_40_0/libs/graph/doc/using_adjacency_list.html#sec:choosing-graph-type">la doc</a>.</p>
<p>On déclare aussi des raccourcis pour les IDs de sommets et d'arcs (en fait, ce sont des unsigned int)</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p429code32'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42932"><td class="code" id="p429code32"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">typedef</span> WayPointGraph<span style="color: #008080;">::</span><span style="color: #007788;">vertex_descriptor</span> WayPointID<span style="color: #008080;">;</span>
<span style="color: #0000ff;">typedef</span> WayPointGraph<span style="color: #008080;">::</span><span style="color: #007788;">edge_descriptor</span>   WayPointConnectionID<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>On va pouvoir instancier notre graphe.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p429code33'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42933"><td class="code" id="p429code33"><pre class="cpp" style="font-family:monospace;">WayPointGraph graphe<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>On commence par rajouter tous les sommets :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p429code34'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42934"><td class="code" id="p429code34"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span>tous nos sommets S<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span>
    WayPointID wpID <span style="color: #000080;">=</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">add_vertex</span><span style="color: #008000;">&#40;</span>graphe<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// wp est l'indice d'un nouveau sommet qui a été ajouté dans graphe</span>
    graphe<span style="color: #008000;">&#91;</span>wpID<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">pos</span> <span style="color: #000080;">=</span> la position du sommet S    <span style="color: #666666;">// graphe[ un WayPointID ] est un WayPoint. On peut donc régler sa position de cette manière.</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Maintenant, on peut les relier par des arcs. Là, c'est à vous de savoir où vont les arcs, boost ne va pas le deviner tout seul...</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p429code35'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42935"><td class="code" id="p429code35"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span>tous nos sommets U<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #666666;">// petit changement de notation, dans boost un arc est souvent décrit entre deux sommets u et v.</span>
    <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span>tous les voisins V de U<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #666666;">// C'est à vous de savoir quels sont les voisins de U.</span>
&nbsp;
        WayPointID u <span style="color: #000080;">=</span> indice de U<span style="color: #008080;">;</span> <span style="color: #666666;">// soit c'est le int du for(), soit il faut y accéder via un autre vector. Cf les notes plus bas.</span>
        WayPointID v <span style="color: #000080;">=</span> indice de V<span style="color: #008080;">;</span>
&nbsp;
        WayPointConnectionID edge<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">bool</span> ok<span style="color: #008080;">;</span>
        boost<span style="color: #008080;">::</span><span style="color: #007788;">tie</span><span style="color: #008000;">&#40;</span>edge, ok<span style="color: #008000;">&#41;</span> <span style="color: #000080;">=</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">add_edge</span><span style="color: #008000;">&#40;</span>u,v, graphe<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// boost::add_edge renvoie une std::pai&gt;WayPointConnectionID,bool&gt;. C'est compliqué à écrire, alors on laisse boost::tie le faire pour nous.</span>
&nbsp;
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>ok<span style="color: #008000;">&#41;</span>  <span style="color: #666666;">// Si le graphe a bel et bien été ajouté ( pas de doublon, par exemple, sauf si spécifié dans le typedef de WayPointGraph )</span>
        graphe<span style="color: #008000;">&#91;</span>edge<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">dist</span> <span style="color: #000080;">=</span> Distance<span style="color: #008000;">&#40;</span>graphe<span style="color: #008000;">&#91;</span>u<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">pos</span>, graphe<span style="color: #008000;">&#91;</span>v<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">pos</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// Longueur d'un arc = distance euclidienne entre les deux sommets u et v.</span>
&nbsp;
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Plusieurs choses sont à remarquer :</p>
<ul>
<li>Personnellement, j'ai utilisé le fait que WayPointID est en fait un int et que dans mon double for(), j'utilise un int pour accéder au waypoint. C'est pas très propre, mais ça évite l'utilisation d'un vector en plus.</li>
<li>graphe[edge] ( edge étant un WayPointConnectionID ) est un WayPointConnection, alors que graphe[u] (u étant un WaypointID) est un WayPoint. On peut donc accéder directement à leurs membres.</li>
<li>Cette dernière remarque est très importante. Cette syntaxe est très appréciable, elle évite d'utiliser les incompréhensibles boost::property_map, elle oblige seulement à avoir un compilateur récent. GCC et Visual s'en sortent très bien.</li>
</ul>
<p>Pour information, mon code à moi ressemble à ça :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p429code36'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42936"><td class="code" id="p429code36"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i<span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i<span style="color: #000080;">&lt;</span>indices.<span style="color: #007788;">size</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">/</span><span style="color: #0000dd;">3</span><span style="color: #008080;">;</span> i<span style="color: #000040;">++</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span>
    ConnectiviteTriangle connectivity<span style="color: #008080;">;</span>
    fillconnectivityinfo<span style="color: #008000;">&#40;</span>i, connectivity, indices<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> c<span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> c<span style="color: #000040;">!</span><span style="color: #000080;">=</span><span style="color: #0000dd;">3</span><span style="color: #008080;">;</span> c<span style="color: #000040;">++</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>connectivity.<span style="color: #007788;">connexe</span><span style="color: #008000;">&#91;</span>c<span style="color: #008000;">&#93;</span><span style="color: #000040;">!</span><span style="color: #000080;">=</span><span style="color: #000040;">-</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span>
        TriangleDescriptor u <span style="color: #000080;">=</span> i<span style="color: #008080;">;</span>
        TriangleDescriptor v <span style="color: #000080;">=</span> connectivity.<span style="color: #007788;">connexe</span><span style="color: #008000;">&#91;</span>c<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>La syntaxe est moyennement cool, mais j'espère que ça vous aidera à mieux comprendre.</p>
<p>Ok, donc maintenant notre graphe a des sommets et des arcs. On va pouvoir faire du pathfinding !</p>
<p>Pour ça, on va avoir besoin de quelques structures :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p429code37'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42937"><td class="code" id="p429code37"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// Une instance de cette structure sera lancée en exception quand on aura trouvé un chemin</span>
<span style="color: #0000ff;">struct</span> found_goal <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #666666;">// Le visiteur, dont le but est de définir une fonction examine_vertex qui dit si on est arrivé au but.</span>
<span style="color: #666666;">// Le but est spécifié via le constructeur.</span>
<span style="color: #0000ff;">class</span> astar_goal_visitor <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">default_astar_visitor</span><span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    astar_goal_visitor<span style="color: #008000;">&#40;</span>WayPointID goal<span style="color: #008000;">&#41;</span> <span style="color: #008080;">:</span> m_goal<span style="color: #008000;">&#40;</span>goal<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">void</span> examine_vertex<span style="color: #008000;">&#40;</span>WayPointID u, <span style="color: #0000ff;">const</span> Graph <span style="color: #000040;">&amp;</span>amp<span style="color: #008080;">;</span> g<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#123;</span> <span style="color: #666666;">// Le const est important.</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>u <span style="color: #000080;">==</span> m_goal<span style="color: #008000;">&#41;</span>
            <span style="color: #0000ff;">throw</span> found_goal<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// On sort en lancant une exception. C'est moche mais c'est comme ça.</span>
        <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    WayPointID m_goal<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Il faut maintenant trouver notre point de départ et notre point d'arrivée. C'est votre problème, mais il faut arriver à quelque chose du style :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p429code38'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42938"><td class="code" id="p429code38"><pre class="cpp" style="font-family:monospace;">TriangleDescriptor goal <span style="color: #000080;">=</span> ...
<span style="color: #007788;">TriangleDescriptor</span> start <span style="color: #000080;">=</span> ...</pre></td></tr></table></div>

<p>Ok, on y va :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p429code39'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42939"><td class="code" id="p429code39"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// Deux vecteurs qui vont servir à sauvegarder le résultat de la recherche</span>
vector<span style="color: #000080;">&lt;</span>WayPointID<span style="color: #000080;">&gt;</span> p<span style="color: #008000;">&#40;</span>boost<span style="color: #008080;">::</span><span style="color: #007788;">num_vertices</span><span style="color: #008000;">&#40;</span>graphe<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// Les prédécesseurs</span>
vector<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">float</span><span style="color: #000080;">&gt;</span>      d<span style="color: #008000;">&#40;</span>boost<span style="color: #008080;">::</span><span style="color: #007788;">num_vertices</span><span style="color: #008000;">&#40;</span>graphe<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #666666;">// Les distances</span>
&nbsp;
<span style="color: #0000ff;">try</span> <span style="color: #008000;">&#123;</span> <span style="color: #666666;">// Encore une fois, la découverte d'un chemin est signalée par une exception, donc il faut un try/catch.</span>
    boost<span style="color: #008080;">::</span><span style="color: #007788;">astar_search</span>
    <span style="color: #008000;">&#40;</span>
        graphe, <span style="color: #666666;">// notre graphe</span>
        start,  <span style="color: #666666;">// notre point de départ</span>
        boost<span style="color: #008080;">::</span><span style="color: #007788;">astar_heuristic</span><span style="color: #000080;">&lt;</span>NavMeshGraph, <span style="color: #0000ff;">float</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, <span style="color: #666666;">// Une heuristique bidon qui renvoie toujours 0</span>
        boost<span style="color: #008080;">::</span><span style="color: #007788;">predecessor_map</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>p<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">distance_map</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>d<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">visitor</span><span style="color: #008000;">&#40;</span>astar_goal_visitor<span style="color: #008000;">&#40;</span>goal<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>.<span style="color: #007788;">weight_map</span><span style="color: #008000;">&#40;</span>boost<span style="color: #008080;">::</span><span style="color: #007788;">get</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>WayPointConnection<span style="color: #008080;">::</span><span style="color: #007788;">dist</span>, graphe<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #666666;">// Voir plus bas</span>
    <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #008000;">&#125;</span> <span style="color: #0000ff;">catch</span><span style="color: #008000;">&#40;</span>found_goal fg<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #666666;">// On a trouvé un chemin</span>
    <span style="color: #666666;">// On suit le chemin trouvé dans le sens inverse</span>
    std<span style="color: #008080;">::</span><span style="color: #007788;">list</span><span style="color: #000080;">&lt;</span>WayPointID<span style="color: #000080;">&gt;</span> shortest_path<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span>WayPointID v <span style="color: #000080;">=</span> goal<span style="color: #008080;">;;</span> v <span style="color: #000080;">=</span> p<span style="color: #008000;">&#91;</span>v<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        shortest_path.<span style="color: #007788;">push_front</span><span style="color: #008000;">&#40;</span>v<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>p<span style="color: #008000;">&#91;</span>v<span style="color: #008000;">&#93;</span> <span style="color: #000080;">==</span> v<span style="color: #008000;">&#41;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #666666;">// et on l'affiche.</span>
    std<span style="color: #008080;">::</span><span style="color: #007788;">list</span><span style="color: #000080;">&lt;</span>WayPointID<span style="color: #000080;">&gt;</span><span style="color: #008080;">::</span><span style="color: #007788;">iterator</span> spi <span style="color: #000080;">=</span> shortest_path.<span style="color: #007788;">begin</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">++</span>spi<span style="color: #008080;">;</span> spi <span style="color: #000040;">!</span><span style="color: #000080;">=</span> shortest_path.<span style="color: #007788;">end</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #000040;">++</span>spi<span style="color: #008000;">&#41;</span>
        Log<span style="color: #008000;">&#40;</span><span style="color: #000040;">*</span>spi<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    Log<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;Total travel time: &quot;</span> , d<span style="color: #008000;">&#91;</span>goal<span style="color: #008000;">&#93;</span> <span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Remarque sur la ligne bizarre:</p>
<ul>
- Ce ne sont pas des virgules, ce sont des points ! Il s'agit d'un seul objet auquel on rajoute plein de propriétés. Cette syntaxe est par exemple utilisée dans la création d'interfaces graphiques : monmenu.addoption("option1").addoption("option2") etc<br />
- A* a besoin de ces quatre propriétés : une map de prédécesseurs, une map de distances, une map de poids, et un visiteur.<br />
- La map de poids est intrisèque au graphe : elle est stockée dans le champ dist des arcs. Mais Boost ne peut pas deviner tout seul que c'est cette variable qu'il faut lire, donc on le lui dit avec boost::get(&amp;WayPointConnection::dist, graphe)</p>
<li>Le visiteur est initialisé avec le goal pour pouvoir lancer son exception si il y a réussite.</li>
</ul>
<p>Vous avez économisé 4 heures de prise de tête avec la doc de BGL, autant d'implémentation de l'A* si vous l'aviez codé vous même, et autant de débug que vous n'aurez jamais à faire : un des grands intérêts des templates, c'est que comme en OCaml, quand ça compile, ça marche (souvent) ^^.</p>
<p>Voyons maintenant comment améliorer un peu notre heuristique : pour l'instant, on n'a fait qu'un parcours brutal de l'arbre, ça ne valait pas trop le coup.<br />
Cela va bien sûr passer par une nouvelle structure :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p429code40'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42940"><td class="code" id="p429code40"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> distance_heuristic <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> boost<span style="color: #008080;">::</span><span style="color: #007788;">astar_heuristic</span> <span style="color: #000080;">&lt;</span>WayPointGraph, <span style="color: #0000ff;">float</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #666666;">// De la même manière que tout à l'heure, on passe les données dont il aura besoin dans son foncteur à la construction.</span>
    distance_heuristic<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> WayPointGraph <span style="color: #000040;">&amp;</span> l, WayPointID goal<span style="color: #008000;">&#41;</span>
    <span style="color: #008080;">:</span> m_graph<span style="color: #008000;">&#40;</span>l<span style="color: #008000;">&#41;</span>, m_goal<span style="color: #008000;">&#40;</span>goal<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">float</span> operator<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span>WayPointID u<span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">const</span> WayPoint <span style="color: #000040;">&amp;</span> U <span style="color: #000080;">=</span> m_graph<span style="color: #008000;">&#91;</span>u<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">const</span> WayPoint <span style="color: #000040;">&amp;</span> V <span style="color: #000080;">=</span> m_graph<span style="color: #008000;">&#91;</span>m_goal<span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">float</span> dx <span style="color: #000080;">=</span> U.<span style="color: #007788;">pos</span>.<span style="color: #007788;">x</span> <span style="color: #000040;">-</span> V.<span style="color: #007788;">pos</span>.<span style="color: #007788;">x</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">float</span> dy <span style="color: #000080;">=</span> U.<span style="color: #007788;">pos</span>.<span style="color: #007788;">y</span> <span style="color: #000040;">-</span> V.<span style="color: #007788;">pos</span>.<span style="color: #007788;">y</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">sqrt</span><span style="color: #008000;">&#40;</span>dx <span style="color: #000040;">*</span> dx <span style="color: #000040;">+</span> dy <span style="color: #000040;">*</span> dy<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">const</span> WayPointGraph <span style="color: #000040;">&amp;</span> m_graph<span style="color: #008080;">;</span>
    TriangleDescriptor m_goal<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>m_graph peut être remplacé ( en changeant le constructeur et l'opérateur ) par n'importe quoi qui vous permette d'obtenir la position d'un vertex à partir de son identifiant. Cela peut être comme ici le graphe lui-même, mais aussi les données à partir duquel il a été construit, etc.</p>
<p>Il suffit maintenant de remplacer boost::astar_heuristic<WayPointGraph, float>() par distance_heuristic(graphe, goal) dans l'appel au A*.</p>
<p>Oh, et au fait : les waypoints ça pue, utilisez des navmeshes.</p>
<p><a href="http://www.coder-studio.com/forum2/viewtopic.php?id=1392">Discussion sur le forum</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.coder-studio.com/blog/tutoriel-boost-graph-library/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>(Petit) Clône de client telnet en Haskell</title>
		<link>http://www.coder-studio.com/blog/petit-clone-de-client-telnet-en-haskell/</link>
		<comments>http://www.coder-studio.com/blog/petit-clone-de-client-telnet-en-haskell/#comments</comments>
		<pubDate>Fri, 28 Aug 2009 11:19:08 +0000</pubDate>
		<dc:creator>Alp Mestan</dc:creator>
				<category><![CDATA[Langages fonctionnels]]></category>
		<category><![CDATA[fonctionnel]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[telnet]]></category>

		<guid isPermaLink="false">http://www.coder-studio.com/blog/?p=421</guid>
		<description><![CDATA[Bonjour, L'autre nuit, muni de café, j'ai souhaité m'amuser avec Haskell. J'ai alors consulté le chapitre sur le réseau en Haskell de Real World Haskell et... j'ai écrit un (très petit) clône de client telnet... qui fait 41 lignes. Le seul soucis étant que dans toute application de ce genre, on doit partager habilement la [...]]]></description>
			<content:encoded><![CDATA[<p>Bonjour,</p>
<p>L'autre nuit, muni de café, j'ai souhaité m'amuser avec Haskell. J'ai alors consulté le chapitre sur le réseau en Haskell de <a href="http://book.realworldhaskell.org/read/">Real World Haskell</a> et... j'ai écrit un (très petit) clône de client telnet... qui fait 41 lignes. Le seul soucis étant que dans toute application de ce genre, on doit partager habilement la lecture des entrées de l'utilisateur, et l'affichage de ce que l'on nous envoie. Ceci mis à part, tout cela fonctionne très bien !</p>
<p><center><img src="http://haskell.org/logos/logos/logo7000.png" alt="Haskell" title="Haskell" /></center></p>
<p><span id="more-421"></span></p>
<p>Regardons à quoi cela ressemble. Petit détail : à chaque tour, je lance la réception de données réseau dans un autre thread, pour ne pas bloquer l'écriture de l'utilisateur.</p>
<p>On importe d'abord les modules nécessaires.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p421code48'); return false;">View Code</a> HASKELL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42148"><td class="code" id="p421code48"><pre class="haskell" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">import</span> Control<span style="color: #339933; font-weight: bold;">.</span>Concurrent 
<span style="color: #06c; font-weight: bold;">import</span> Control<span style="color: #339933; font-weight: bold;">.</span><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Monad"><span style="color: #cccc00; font-weight: bold;">Monad</span></a> 
<span style="color: #06c; font-weight: bold;">import</span> Network<span style="color: #339933; font-weight: bold;">.</span>Socket 
<span style="color: #06c; font-weight: bold;">import</span> Network<span style="color: #339933; font-weight: bold;">.</span>BSD 
<span style="color: #06c; font-weight: bold;">import</span> System<span style="color: #339933; font-weight: bold;">.</span>Environment 
<span style="color: #06c; font-weight: bold;">import</span> System<span style="color: #339933; font-weight: bold;">.</span><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:IO"><span style="color: #cccc00; font-weight: bold;">IO</span></a></pre></td></tr></table></div>

<p>Ensuite, j'ai écrit quelques fonctions pour rendre la connection, l'envoi etc plus faciles.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p421code49'); return false;">View Code</a> HASKELL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42149"><td class="code" id="p421code49"><pre class="haskell" style="font-family:monospace;"><span style="color: #5d478b; font-style: italic;">-- Ouverture d'une connexion TCP cliente </span>
<span style="color: #5d478b; font-style: italic;">-- Prend en argument l'host et le port/service (qui est une String également) </span>
<span style="color: #5d478b; font-style: italic;">-- Retourne le &quot;Handle&quot; vers le socket en question. </span>
openConnection <span style="color: #339933; font-weight: bold;">::</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:String"><span style="color: #cccc00; font-weight: bold;">String</span></a> <span style="color: #339933; font-weight: bold;">-&gt;</span> ServiceName <span style="color: #339933; font-weight: bold;">-&gt;</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:IO"><span style="color: #cccc00; font-weight: bold;">IO</span></a> Handle 
openConnection hostname port <span style="color: #339933; font-weight: bold;">=</span> 
  <span style="color: #06c; font-weight: bold;">do</span> 
  addrInfos <span style="color: #339933; font-weight: bold;">&lt;-</span> getAddrInfo Nothing <span style="color: green;">&#40;</span>Just hostname<span style="color: green;">&#41;</span> <span style="color: green;">&#40;</span>Just port<span style="color: green;">&#41;</span> 
  <span style="color: #06c; font-weight: bold;">let</span> serveraddr <span style="color: #339933; font-weight: bold;">=</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:head"><span style="font-weight: bold;">head</span></a> addrInfos 
  sock <span style="color: #339933; font-weight: bold;">&lt;-</span> socket <span style="color: green;">&#40;</span>addrFamily serveraddr<span style="color: green;">&#41;</span> Stream defaultProtocol 
  setSocketOption sock KeepAlive <span style="color: red;">1</span> 
  connect sock <span style="color: green;">&#40;</span>addrAddress serveraddr<span style="color: green;">&#41;</span> 
  h <span style="color: #339933; font-weight: bold;">&lt;-</span> socketToHandle sock ReadWriteMode 
  hSetBuffering h <span style="color: green;">&#40;</span>BlockBuffering Nothing<span style="color: green;">&#41;</span> 
  <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:return"><span style="font-weight: bold;">return</span></a> h 
&nbsp;
<span style="color: #5d478b; font-style: italic;">-- Ferme la connexion dont le Handle est donné </span>
closeConnection <span style="color: #339933; font-weight: bold;">::</span> Handle <span style="color: #339933; font-weight: bold;">-&gt;</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:IO"><span style="color: #cccc00; font-weight: bold;">IO</span></a> <span style="color: green;">&#40;</span><span style="color: green;">&#41;</span> 
closeConnection h <span style="color: #339933; font-weight: bold;">=</span> hClose h 
&nbsp;
<span style="color: #5d478b; font-style: italic;">-- Envoie la chaîne donnée sur le Handle donné, et ensuite fait un flush sur ce handle, ce qui force l'envoi immédiat et nettoie les états </span>
sendMsg <span style="color: #339933; font-weight: bold;">::</span> Handle <span style="color: #339933; font-weight: bold;">-&gt;</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:String"><span style="color: #cccc00; font-weight: bold;">String</span></a> <span style="color: #339933; font-weight: bold;">-&gt;</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:IO"><span style="color: #cccc00; font-weight: bold;">IO</span></a> <span style="color: green;">&#40;</span><span style="color: green;">&#41;</span> 
sendMsg h msg <span style="color: #339933; font-weight: bold;">=</span> hPutStrLn h msg <span style="color: #339933; font-weight: bold;">&gt;&gt;</span> hFlush h 
&nbsp;
<span style="color: #5d478b; font-style: italic;">-- Lis sur le Handle donné une chaîne et la renvoie (dans la monade IO) </span>
recvMsg <span style="color: #339933; font-weight: bold;">::</span> Handle <span style="color: #339933; font-weight: bold;">-&gt;</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:IO"><span style="color: #cccc00; font-weight: bold;">IO</span></a> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:String"><span style="color: #cccc00; font-weight: bold;">String</span></a> 
recvMsg h <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">do</span> 
  msg <span style="color: #339933; font-weight: bold;">&lt;-</span> hGetContents h  
  <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:return"><span style="font-weight: bold;">return</span></a> msg</pre></td></tr></table></div>

<p>Voyons maintenant la fonction main.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p421code50'); return false;">View Code</a> HASKELL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42150"><td class="code" id="p421code50"><pre class="haskell" style="font-family:monospace;">main <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">do</span> 
  args <span style="color: #339933; font-weight: bold;">&lt;-</span> getArgs 
  <span style="color: #06c; font-weight: bold;">let</span> <span style="color: green;">&#40;</span>host<span style="color: #339933; font-weight: bold;">,</span> port<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#40;</span>args <span style="color: #339933; font-weight: bold;">!!</span> <span style="color: red;">0</span><span style="color: #339933; font-weight: bold;">,</span> args <span style="color: #339933; font-weight: bold;">!!</span> <span style="color: red;">1</span><span style="color: green;">&#41;</span></pre></td></tr></table></div>

<p>On récupère les arguments donnés au programme (s'il n'y en a pas assez, cela fera planter le logiciel -- je ne me suis pas vraiment préoccupé de tous les cas d'erreur, mais ce n'était pas ma priorité ici) via la fonction getArgs, et l'on en récupère l'host et le port donnés.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p421code51'); return false;">View Code</a> HASKELL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42151"><td class="code" id="p421code51"><pre class="haskell" style="font-family:monospace;">  <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:putStrLn"><span style="font-weight: bold;">putStrLn</span></a> <span style="color: #339933; font-weight: bold;">$</span> <span style="background-color: #3cb371;">&quot;Opening client on &quot;</span> <span style="color: #339933; font-weight: bold;">++</span> host <span style="color: #339933; font-weight: bold;">++</span> <span style="background-color: #3cb371;">&quot;:&quot;</span> <span style="color: #339933; font-weight: bold;">++</span> port <span style="color: #339933; font-weight: bold;">++</span> <span style="background-color: #3cb371;">&quot;<span style="background-color: #3cb371; font-weight: bold;">\n</span>&quot;</span> 
  hclient <span style="color: #339933; font-weight: bold;">&lt;-</span> openConnection host port 
  <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:putStrLn"><span style="font-weight: bold;">putStrLn</span></a> <span style="background-color: #3cb371;">&quot;Client connected&quot;</span></pre></td></tr></table></div>

<p>Ca y est, on se connecte, en affichant des messages pour tenir l'utilisateur informé. Si la connection échoue, le programme s'arrêtera avec une erreur -- cf remarque ci-dessus.</p>
<p>Et maintenant, la boucle qui permet de lire depuis le réseau et lire depuis l'utilisateur, etc.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p421code52'); return false;">View Code</a> HASKELL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42152"><td class="code" id="p421code52"><pre class="haskell" style="font-family:monospace;">  forever <span style="color: #339933; font-weight: bold;">$</span> <span style="color: #06c; font-weight: bold;">do</span> 
    <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:getLine"><span style="font-weight: bold;">getLine</span></a> <span style="color: #339933; font-weight: bold;">&gt;&gt;=</span> sendMsg hclient 
    forkIO <span style="color: #339933; font-weight: bold;">$</span> recvMsg hclient <span style="color: #339933; font-weight: bold;">&gt;&gt;=</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:putStrLn"><span style="font-weight: bold;">putStrLn</span></a></pre></td></tr></table></div>

<p>Ici, on a une sorte de boucle "à la while(true)", dans laquelle on va tour à tour récupérer une entrée de l'utilisateur et l'envoyer au serveur, puis, dans un thread séparé, récupérer ce qu'a envoyé le serveur et l'afficher.<br />
Enfin, on ferme la connection (ce code est inutile tant que l'on a pas de possibilité de sortir du forever... qui devra tôt ou tard se transformer en "until" ou autre).</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p421code53'); return false;">View Code</a> HASKELL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42153"><td class="code" id="p421code53"><pre class="haskell" style="font-family:monospace;">  closeConnection hclient</pre></td></tr></table></div>

<p>Voilà le code complet :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p421code54'); return false;">View Code</a> HASKELL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p42154"><td class="code" id="p421code54"><pre class="haskell" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">import</span> Control<span style="color: #339933; font-weight: bold;">.</span>Concurrent 
<span style="color: #06c; font-weight: bold;">import</span> Control<span style="color: #339933; font-weight: bold;">.</span><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:Monad"><span style="color: #cccc00; font-weight: bold;">Monad</span></a> 
<span style="color: #06c; font-weight: bold;">import</span> Network<span style="color: #339933; font-weight: bold;">.</span>Socket 
<span style="color: #06c; font-weight: bold;">import</span> Network<span style="color: #339933; font-weight: bold;">.</span>BSD 
<span style="color: #06c; font-weight: bold;">import</span> System<span style="color: #339933; font-weight: bold;">.</span>Environment 
<span style="color: #06c; font-weight: bold;">import</span> System<span style="color: #339933; font-weight: bold;">.</span><a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:IO"><span style="color: #cccc00; font-weight: bold;">IO</span></a> 
&nbsp;
openConnection <span style="color: #339933; font-weight: bold;">::</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:String"><span style="color: #cccc00; font-weight: bold;">String</span></a> <span style="color: #339933; font-weight: bold;">-&gt;</span> ServiceName <span style="color: #339933; font-weight: bold;">-&gt;</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:IO"><span style="color: #cccc00; font-weight: bold;">IO</span></a> Handle 
openConnection hostname port <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">do</span> 
  addrInfos <span style="color: #339933; font-weight: bold;">&lt;-</span> getAddrInfo Nothing <span style="color: green;">&#40;</span>Just hostname<span style="color: green;">&#41;</span> <span style="color: green;">&#40;</span>Just port<span style="color: green;">&#41;</span> 
  <span style="color: #06c; font-weight: bold;">let</span> serveraddr <span style="color: #339933; font-weight: bold;">=</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:head"><span style="font-weight: bold;">head</span></a> addrInfos 
  sock <span style="color: #339933; font-weight: bold;">&lt;-</span> socket <span style="color: green;">&#40;</span>addrFamily serveraddr<span style="color: green;">&#41;</span> Stream defaultProtocol 
  setSocketOption sock KeepAlive <span style="color: red;">1</span> 
  connect sock <span style="color: green;">&#40;</span>addrAddress serveraddr<span style="color: green;">&#41;</span> 
  h <span style="color: #339933; font-weight: bold;">&lt;-</span> socketToHandle sock ReadWriteMode 
  hSetBuffering h <span style="color: green;">&#40;</span>BlockBuffering Nothing<span style="color: green;">&#41;</span> 
  <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:return"><span style="font-weight: bold;">return</span></a> h 
&nbsp;
closeConnection <span style="color: #339933; font-weight: bold;">::</span> Handle <span style="color: #339933; font-weight: bold;">-&gt;</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:IO"><span style="color: #cccc00; font-weight: bold;">IO</span></a> <span style="color: green;">&#40;</span><span style="color: green;">&#41;</span> 
closeConnection h <span style="color: #339933; font-weight: bold;">=</span> hClose h 
&nbsp;
sendMsg <span style="color: #339933; font-weight: bold;">::</span> Handle <span style="color: #339933; font-weight: bold;">-&gt;</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:String"><span style="color: #cccc00; font-weight: bold;">String</span></a> <span style="color: #339933; font-weight: bold;">-&gt;</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:IO"><span style="color: #cccc00; font-weight: bold;">IO</span></a> <span style="color: green;">&#40;</span><span style="color: green;">&#41;</span> 
sendMsg h msg <span style="color: #339933; font-weight: bold;">=</span> hPutStrLn h msg <span style="color: #339933; font-weight: bold;">&gt;&gt;</span> hFlush h 
&nbsp;
recvMsg <span style="color: #339933; font-weight: bold;">::</span> Handle <span style="color: #339933; font-weight: bold;">-&gt;</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:IO"><span style="color: #cccc00; font-weight: bold;">IO</span></a> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#t:String"><span style="color: #cccc00; font-weight: bold;">String</span></a> 
recvMsg h <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">do</span> 
  msg <span style="color: #339933; font-weight: bold;">&lt;-</span> hGetContents h  
  <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:return"><span style="font-weight: bold;">return</span></a> msg 
&nbsp;
main <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">do</span> 
  args <span style="color: #339933; font-weight: bold;">&lt;-</span> getArgs 
  <span style="color: #06c; font-weight: bold;">let</span> <span style="color: green;">&#40;</span>host<span style="color: #339933; font-weight: bold;">,</span> port<span style="color: green;">&#41;</span> <span style="color: #339933; font-weight: bold;">=</span> <span style="color: green;">&#40;</span>args <span style="color: #339933; font-weight: bold;">!!</span> <span style="color: red;">0</span><span style="color: #339933; font-weight: bold;">,</span> args <span style="color: #339933; font-weight: bold;">!!</span> <span style="color: red;">1</span><span style="color: green;">&#41;</span> 
  <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:putStrLn"><span style="font-weight: bold;">putStrLn</span></a> <span style="color: #339933; font-weight: bold;">$</span> <span style="background-color: #3cb371;">&quot;Opening client on &quot;</span> <span style="color: #339933; font-weight: bold;">++</span> host <span style="color: #339933; font-weight: bold;">++</span> <span style="background-color: #3cb371;">&quot;:&quot;</span> <span style="color: #339933; font-weight: bold;">++</span> port <span style="color: #339933; font-weight: bold;">++</span> <span style="background-color: #3cb371;">&quot;<span style="background-color: #3cb371; font-weight: bold;">\n</span>&quot;</span> 
  hclient <span style="color: #339933; font-weight: bold;">&lt;-</span> openConnection host port 
  <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:putStrLn"><span style="font-weight: bold;">putStrLn</span></a> <span style="background-color: #3cb371;">&quot;Client connected&quot;</span> 
  forever <span style="color: #339933; font-weight: bold;">$</span> <span style="color: #06c; font-weight: bold;">do</span> 
    <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:getLine"><span style="font-weight: bold;">getLine</span></a> <span style="color: #339933; font-weight: bold;">&gt;&gt;=</span> sendMsg hclient 
    forkIO <span style="color: #339933; font-weight: bold;">$</span> recvMsg hclient <span style="color: #339933; font-weight: bold;">&gt;&gt;=</span> <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:putStrLn"><span style="font-weight: bold;">putStrLn</span></a> 
  closeConnection hclient</pre></td></tr></table></div>

<p>Compilation :</p>
<blockquote><p>ghc --make -o net net.hs</p></blockquote>
<p>Puis 2 exemples d'exécution...<br />
<code>
<pre>
$ ./net google.fr 80
Opening client on google.fr:80
Client connected
GET / HTTP/1.0
HTTP/1.0 302 Found
Location: http://www.google.fr/
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Set-Cookie: PREF=ID=30b094ad566b5532:TM=1251456529:LM=1251456529:S=94IXp5-SGiaYADWc; expires=Sun, 28-Aug-2011 10:48:49 GMT; path=/; domain=.google.com
Date: Fri, 28 Aug 2009 10:48:49 GMT
Server: gws
Content-Length: 218 

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.fr/">here</A>.
</BODY></HTML> 

^C
</pre>
<p></code><br />
(c'est moi qui ai tapé "GET / HTTP/1.0")<br />
( qui vous dira que la page a été déplacée <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  )</p>
<p>Et enfin, la surprise...</p>
<blockquote><p>$ ./net towel.blinkenlights.nl 23</p></blockquote>
<p>Qui, une version simplifiée d'un film très connu, vous permettra de voir, Jedi.</p>
<p>Enjoy !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coder-studio.com/blog/petit-clone-de-client-telnet-en-haskell/feed/</wfw:commentRss>
		<slash:comments>3006</slash:comments>
		</item>
		<item>
		<title>CipherSaber - Chiffrement en kit</title>
		<link>http://www.coder-studio.com/blog/ciphersaber-chiffrement-en-kit/</link>
		<comments>http://www.coder-studio.com/blog/ciphersaber-chiffrement-en-kit/#comments</comments>
		<pubDate>Thu, 13 Aug 2009 22:07:59 +0000</pubDate>
		<dc:creator>Wett</dc:creator>
				<category><![CDATA[Non classé]]></category>
		<category><![CDATA[ARC4]]></category>
		<category><![CDATA[ARCFOUR]]></category>
		<category><![CDATA[Chiffrement]]></category>
		<category><![CDATA[CipherSaber]]></category>
		<category><![CDATA[Cryptage]]></category>
		<category><![CDATA[RC4]]></category>

		<guid isPermaLink="false">http://www.coder-studio.com/blog/?p=404</guid>
		<description><![CDATA[CipherSaber, c'est la reprise du concept selon lequel il faut en savoir faire un minimum, tout seul, comme un grand. A l'instar des Jedis dans l'univers Star Wars qui vont réaliser eux-même leur sabre laser (vous comprenez maintenant le nom du projet), on nous propose de réaliser nous-même notre petit logiciel de chiffrement. ]]></description>
			<content:encoded><![CDATA[<h2>Sabre <span style="text-decoration: line-through;">laser</span> de chiffrement</h2>
<p>Au détour d'une naviguation web fortuite mais bienheureuse, je suis tombé sur <a title="CipherSaber" href="http://ciphersaber.gurus.org/">CipherSaber</a>. Vous savez, c'est ce genre de moment où on tombe sur une initiative sympa, facile à suivre et qui fait sens. Bref, j'ai accroché tout de suite, alors j'ai laissé tomber ce que j'étais en train de faire et y ai consacré mes heures suivantes.<br />
CipherSaber, c'est la reprise du concept selon lequel il faut en savoir faire un minimum, tout seul, comme un grand. A l'instar des Jedis dans l'univers Star Wars qui vont réaliser eux-même leur sabre laser (vous comprenez maintenant le nom du projet), on nous propose de réaliser nous-même notre petit logiciel de chiffrement.<span id="more-404"></span> Je vous laisse parcourir le site pour une explication plus en détail de la philosophie derrière ce petit combat pour la cryptographie, mais l'idée est là : A n'importe quel moment, nous devrions être capable de produire un logiciel de chiffrement suffisamment solide pour être utilisé sans risque, afin de s'affranchir des éventuelles lois contre l'exportation et garantir notre liberté de parole, autant que faire se peut. Joli programme !<br />
Voici les instructions que l'on nous fournit pour réaliser cet outil (directement traduites depuis le lien du début de l'article) :</p>
<ol>
<li> Utiliser l'algorithme de chiffrement ARCFOUR (ou RC4), tel que décrit par exemple <a title="ici" href="http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt">ici</a>.</li>
<li>Chaque fichier chiffré se compose d'un Vecteur d'Initialisation (IV) de 10 octets, puis du contenu chiffré. Un nouveau vecteur aléatoire devra être généré à chaque chiffrement de fichier.</li>
<li>La clé de chiffrement se compose elle de la clé que l'utilisateur nous fournit suivie de ce même Vecteur d'Initialisation.</li>
</ol>
<p>Et effectivement, ce sont les seules indications dont nous aurons besoin. Une fois le programme réalisé, nous aurons la possibilité de déchiffrer un certificat en gif, preuve de notre petite réussite. Si l'idée vous plait et que vous souhaitez vous contenter de ces informations pour vous-même construire votre CipherSaber, alors ne revenez lire la suite de cet article que quand vous aurez votre certificat !</p>
<h2>ARCFOUR ?</h2>
<p>ARCFOUR, c'est l'algorithme libre identique au RC4 qui lui est une propriété de RSA Security. Ici, pas de clé publique/privée, pas d'algorithme alambiqué, mais une solution implémentable "de tête", pour peu qu'on fasse l'effort de la comprendre et d'en retenir les fondements.</p>
<p>Bon, ok, c'est gentil, mais le ARCFOUR moi, je ne le connais pas. Qu'à cela ne tienne, il suffira de suivre le lien donné ou de rechercher RC4 sur le web pour que l'algorithme nous tombe tout cru, ou presque. Mais j'insiste, le but ici est de pouvoir à tout moment réécrire ce logiciel de mémoire, donc on apportera un soin tout particulier à en retenir les principes de fonctionnement.</p>
<p>C'est un algorithme de chiffrement à flot, il repose sur deux phases :</p>
<ol>
<li>A partir de la clé K que nous donne l'utilisateur, on va générer un tableau d'état S que l'on va mélanger de nombreuses fois afin d'obtenir une suite de chiffres pseudo-aléatoires.</li>
<li>On va ensuite chiffrer le contenu sensible par un simple XOR entre ses octets et ceux du tableau d'état. Si c'est votre tout premier pas dans le monde de la cryptographie, sachez que l'opération XOR est "réversible" (il y a sûrement un terme mathématique approprié à cette propriété, pardon à eux pour mon ignorance), c'est à dire que si A xor B = C, alors A xor C = B. On utilise donc exactement la même procédure et la même clé pour chiffrer et déchiffrer.</li>
</ol>
<p>Maintenant qu'on saisit la généralité de la méthode, voyons comment la réaliser plus en détail :</p>
<ol>
<li>Créons notre tableau d'état :
<ol>
<li>Soit la clé K d'une taille de 256 octets (si elle fait moins, on la répète à la suite jusqu'à obtenir 256 octets pile)</li>
<li>Construisons un tableau S de 256 valeurs, chacune contenant son index basé à 0 : S[0] = 0, S[255]=255.</li>
<li>Mélangeons S, avec i allant de 0 à 255 et j démarrant à 0:
<ol>
<li>Inverser l'élément i de S <em>avec celui de rang</em> (S[i]+K[i])+j, j étant le rang du "mélangé" précédent. Autrement dit, ajouter S[i]+K[i] à j et inverser S[i] et S[j]</li>
</ol>
</li>
</ol>
</li>
<li>Chiffrons :
<ol>
<li>Boucler sur chaque octet du fichier à chiffrer, et avec i et j démarrant à 0 :
<ol>
<li>incrémenter i</li>
<li>Un peu comme précédemment, inverser l'élément i de S avec celui de rang (S[i]+j), j étant le rang du mélangé précédent. Autrement dit, ajouter S[i] à j et inverser S[i] et S[j]</li>
<li>Combiner l'octet à chiffrer avec la valeur de l'élément S[i]+S[j] par un XOR.</li>
</ol>
</li>
</ol>
</li>
</ol>
<p>J'ai conscience que ce n'est sûrement pas clair au premier abord, mais j'ai essayé ici de résumer l'algorithme par ses opérations logiques, afin que ce soit appréhendable pour l'esprit et donc plus aisé à retenir. Pour une version plus proche de l'implémentation, il vous reste votre moteur de recherche préféré. Retenez par contre un détail important : Chaque éléments de chaque tableau est un octet, il en va de même pour i et j. Par conséquent, <strong>chaque addition se fait modulo 256</strong>.</p>
<p>Une fois votre implémentation écrite, n'hésitez pas à la tester. Un petit chiffrement/dechiffrement pour s'assurer que tout va bien ne sera pas de trop, croyez-moi.</p>
<h2>IVs et tests</h2>
<p>Maintenant que votre ARC4 est implémenté et testé, reste à en faire quelque chose. Oui car utilisé tel quel, c'est un algorithme tout à fait prévisible, or nous recherchons un chiffrement suffisament fort. La règle qui semble être celle de base, c'est qu'un même chiffrement appliqué à un même fichier ne doit pas donner le même résultat. L'idée est donc d'ajouter un IV, l'Initialisation Vector dont on parlait plus haut.  Ainsi, lors du chiffrement, on va générer un IV <em>aléatoire</em> de 10 octets, qu'on va :</p>
<ul>
<li>Mettre à la suite de la clé que nous a fourni l'utilisateur pour produire une clé <em>unique</em> à fournir à l'argorithme de chiffrement</li>
<li>Ajouter en clair au début du fichier crypté, afin quand même que l'on puisse connaitre la clé à utiliser pour déchiffrer.</li>
</ul>
<p>L'IV est donc une donnée "publique" puisqu'en clair, mais cela suffit à notre besoin de non-répétition. Par contre son choix est important, crucial même, alors attention à la méthode de génération pseudo aléatoire que vous allez utiliser.</p>
<p>Et voilà ! Une fois ce dernier détail implémenté, il ne vous reste plus qu'à tester votre programme sur les fichiers chiffrés fournis sur le site. Si vos tests ne fonctionnent pas, vous trouverez dans la FAQ quelques points à vérifier dans votre code pour trouver le bug. Voici ceux qui m'ont servi :</p>
<ul>
<li> Si vous programmez en C/C++, ouvrez vos fichiers en binaire... On aurait tendance à l'oublier.</li>
<li>Double, triple-vérifiez vos index et les combinaisons de tailles, ajout, suppression, décalages.</li>
</ul>
<h2>Aller un peu plus loin</h2>
<p>Ainsi que vous avez peut-être lu quelque part, certaines faiblesses ont été décelées dans l'ARC4. Elles sont notamment à la base des attaques contre le protocole WEP maintenant si rapides qu'on peut faire tomber un réseau Wifi en 15 minutes. L'auteur recommande donc de passer à... CipherSaber 2 ! &lt;Musique épique, et là avouez, ça picote !&gt;</p>
<p>En fait ce n'est qu'une petite évolution de votre programme actuel : le moyen le plus simple de sécuriser son CipherSaber est de démultiplier le nombre de mélanges de S. Ainsi, à l'étape 3 de la création de notre tableau d'état décrite ci-dessus, on va non pas effectuer ce mélange complet de S une fois mais N fois, N étant une donnée qu'il faudra bien évidemment connaitre lors du déchiffrement. Pour être tranquille, utilisez un N de 15 ou 20.</p>
<h2>Aller vraiment au bout de son sabre</h2>
<p>Mais toute bonne votre méthode de chiffrement soit-elle, si vous utilisez une passphrase de 3 lettres ou votre date d'anniversaire, tout cela n'aura servi à rien. Ce n'est pas le but de l'article que de décrire un moyen efficace d'en générer une, mais sachez qu'il existe des méthodes comme celle décrite sur <a title="Diceware" href="http://world.std.com/~reinhold/diceware.html">Diceware</a> (c'est depuis ce site que j'ai découvert CipherSabre, ce n'est donc pas par hasard que je met ce lien ici). Retenez tout de même qu'un mot de passe n'est pas une.. hm, et bien phrase de passe. Le premier est adapté à un contexte local, lorsque vous avez besoin d'un mot court à entropie forte. La passphrase, de ce que j'en comprend, permet de s'affranchir plus ou moins du coté "impossible à retenir" d'un vrai de mot de passe fort, en augmentant la taille de la clé à 15 ou 20 caractères avec des mots courants, tout en fournissant pour peu qu'elle soit bien choisie (aléatoire) un entropie plus que satisfaisante.</p>
<h2>Et alors ?</h2>
<p>Et bien voilà, maintenant vous savez écrire un logiciel de chiffrement. Gardez bien-sûr conscience qu'il ne remplacera jamais une vraie solution comme OpenPGP, qui malgré sa puissance est deja suffisament mal diffusée pour qu'on n'en rajoute pas à vouloir utiliser notre solution personnelle moins pratique et moins sûre. Mais enfin, à votre niveau vous savez reproduire tout seul un outil basique mais potentiellement utile en situation réelle, vous avez limité votre dépendance à ceux qui savent, ceux qui dirigent, ceux en qui on vous demande d'avoir une confiance presque aveugle. Et enfin, vous en aurez un peu appris sur les fondements de la cryptographie, peut-être plus qu'en jouant avec AirCrack sur votre propre réseau ou celui du voisin...</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coder-studio.com/blog/ciphersaber-chiffrement-en-kit/feed/</wfw:commentRss>
		<slash:comments>3854</slash:comments>
		</item>
		<item>
		<title>Haskell Platform, ou comment se mettre à Haskell sans soucis !</title>
		<link>http://www.coder-studio.com/blog/haskell-platform-ou-comment-se-mettre-a-haskell-sans-soucis/</link>
		<comments>http://www.coder-studio.com/blog/haskell-platform-ou-comment-se-mettre-a-haskell-sans-soucis/#comments</comments>
		<pubDate>Wed, 12 Aug 2009 08:19:14 +0000</pubDate>
		<dc:creator>Alp Mestan</dc:creator>
				<category><![CDATA[Langages fonctionnels]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[platform]]></category>

		<guid isPermaLink="false">http://www.coder-studio.com/blog/?p=401</guid>
		<description><![CDATA[Bonjour à tous, Cela fait quelques temps maintenant que la communauté Haskell a sorti Haskell Platform. Il s'agit d'un "paquet" qui regroupe : - le compilateur haskell GHC, un debugger, un profiler, etc - les bibliothèques les plus populaires et les plus utilisées, fournies d'office - tout un tas d'outils auxiliaires, comme haddock, qui permet [...]]]></description>
			<content:encoded><![CDATA[<p>Bonjour à tous,</p>
<p>Cela fait quelques temps maintenant que la communauté <a href="http://www.haskell.org/">Haskell</a> a sorti <strong><a href="http://hackage.haskell.org/platform/">Haskell Platform</a></strong>. Il s'agit d'un "paquet" qui regroupe :<br />
- le compilateur haskell GHC, un debugger, un profiler, etc<br />
- les bibliothèques les plus populaires et les plus utilisées, fournies d'office<br />
- tout un tas d'outils auxiliaires, comme <em>haddock</em>, qui permet de générer de la documentation depuis les commentaires du code source.</p>
<p>Il existe des paquets pour déjà quelques distributions Linux, sachant que ce sera bientôt prêt pour Debian et Ubuntu également. Les installeurs Windows et Mac sont très simples également.</p>
<p>Bref, plus aucune raison de ne pas essayer Haskell <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.coder-studio.com/blog/haskell-platform-ou-comment-se-mettre-a-haskell-sans-soucis/feed/</wfw:commentRss>
		<slash:comments>3127</slash:comments>
		</item>
		<item>
		<title>Préprocesseur et énumérations : la suite.</title>
		<link>http://www.coder-studio.com/blog/preprocesseur-et-enumerations-la-suite/</link>
		<comments>http://www.coder-studio.com/blog/preprocesseur-et-enumerations-la-suite/#comments</comments>
		<pubDate>Wed, 15 Jul 2009 20:34:09 +0000</pubDate>
		<dc:creator>Funto</dc:creator>
				<category><![CDATA[C & C++]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[énumération]]></category>
		<category><![CDATA[préprocesseur]]></category>
		<category><![CDATA[template]]></category>

		<guid isPermaLink="false">http://www.coder-studio.com/blog/?p=393</guid>
		<description><![CDATA[Cet article fait suite à mon premier article intitulé "Faire un peu joujou avec le préprocesseur" (disponible ici : http://www.coder-studio.com/blog/preproc/ ). Pour rappel, nous en sommes restés à un système de macro qui permettait d'automatiser la création d'un opérateur "]]></description>
			<content:encoded><![CDATA[<p>Cet article fait suite à mon premier article intitulé "Faire un peu joujou avec le préprocesseur"<br />
(disponible ici : http://www.coder-studio.com/blog/preproc/ ).</p>
<p>Pour rappel, nous en sommes restés à un système de macro qui permettait d'automatiser la création<br />
d'un opérateur "<<" pour iostream, capable d'afficher le nom d'une énumération.</p>
<p><span id="more-393"></span></p>
<p>Voici le code :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code67'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39367"><td class="code" id="p393code67"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// Enumerate.h</span>
&nbsp;
<span style="color: #339900;">#ifndef ENUMERATE_H</span>
<span style="color: #339900;">#define ENUMERATE_H</span>
&nbsp;
<span style="color: #339900;">#define MAKE_ENUM(enum_name, ...)	\
	enum enum_name { __VA_ARGS__ };</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_1(val)	\
	case val:	\
		os &lt;&lt; #val;	\
		break;</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_2(val, ...)	ENUM_CASE_1(val) ENUM_CASE_1(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_3(val, ...)	ENUM_CASE_1(val) ENUM_CASE_2(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_4(val, ...)	ENUM_CASE_1(val) ENUM_CASE_3(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_5(val, ...)	ENUM_CASE_1(val) ENUM_CASE_4(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_6(val, ...)	ENUM_CASE_1(val) ENUM_CASE_5(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_7(val, ...)	ENUM_CASE_1(val) ENUM_CASE_6(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_8(val, ...)	ENUM_CASE_1(val) ENUM_CASE_7(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_9(val, ...)	ENUM_CASE_1(val) ENUM_CASE_8(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_10(val, ...)	ENUM_CASE_1(val) ENUM_CASE_9(__VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_N(nb_vals, ...) ENUM_CASE_ ## nb_vals(__VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#define MAKE_OPERATOR(nb_vals, enum_name, ...)	\
	inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const enum_name&amp; e)	{\
		switch(e) {	\
			ENUM_CASE_N(nb_vals, __VA_ARGS__)	\
		}	\
		return os;	\
	}</span>
&nbsp;
&nbsp;
<span style="color: #339900;">#define ENUMERATE(nb_vals, enum_name, ...)	\
	MAKE_ENUM(enum_name, __VA_ARGS__)	\
	MAKE_OPERATOR(nb_vals, enum_name, __VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#endif // ENUMERATE_H</span></pre></td></tr></table></div>


<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code68'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39368"><td class="code" id="p393code68"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// main.cpp</span>
&nbsp;
<span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &quot;Enumerate.h&quot;</span>
&nbsp;
ENUMERATE<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">3</span>, MonEnumeration,
	E_VAL_1,
	E_VAL_2,
	E_VAL_3<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	MonEnumeration e <span style="color: #000080;">=</span> E_VAL_1<span style="color: #008080;">;</span>
	std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> e <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Le plus gros problème de ce système est le fait que l'on soit obligés de donner le nombre de valeurs de l'énumération<br />
lors de l'utilisation de la macro ENUMERATE.</p>
<p>Ce qui nous oblige à spécifier ce numéro, c'est la nécessiter de "choisir" la bonne macro parmi ENUM_CASE_1, ENUM_CASE_2, ..., ENUM_CASE_10.</p>
<p>Se passer de ce nombre, c'est effectuer l' "appel récursif" jusqu'à ce qu'il n'y ait plus d'argument à traiter dans la<br />
"liste" __VA_ARGS__.</p>
<p>Que se passe-t-il si l'on supprime ce nombre et que l'on remplace l'appel à ENUM_CASE_N par la version qui gère le plus d'arguments<br />
(ici ENUM_CASE_10, donc) ?</p>
<p>Version remaniée :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code69'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39369"><td class="code" id="p393code69"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// Enumerate.h</span>
&nbsp;
<span style="color: #339900;">#ifndef ENUMERATE_H</span>
<span style="color: #339900;">#define ENUMERATE_H</span>
&nbsp;
<span style="color: #339900;">#define MAKE_ENUM(enum_name, ...)	\
	enum enum_name { __VA_ARGS__ };</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_1(val)	\
	case val:	\
		os &lt;&lt; #val;	\
		break;</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_2(val, ...)	ENUM_CASE_1(val) ENUM_CASE_1(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_3(val, ...)	ENUM_CASE_1(val) ENUM_CASE_2(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_4(val, ...)	ENUM_CASE_1(val) ENUM_CASE_3(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_5(val, ...)	ENUM_CASE_1(val) ENUM_CASE_4(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_6(val, ...)	ENUM_CASE_1(val) ENUM_CASE_5(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_7(val, ...)	ENUM_CASE_1(val) ENUM_CASE_6(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_8(val, ...)	ENUM_CASE_1(val) ENUM_CASE_7(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_9(val, ...)	ENUM_CASE_1(val) ENUM_CASE_8(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_10(val, ...)	ENUM_CASE_1(val) ENUM_CASE_9(__VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#define MAKE_OPERATOR(enum_name, ...)	\
	inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const enum_name&amp; e)	{\
		switch(e) {	\
			ENUM_CASE_10(__VA_ARGS__)	\
		}	\
		return os;	\
	}</span>
&nbsp;
&nbsp;
<span style="color: #339900;">#define ENUMERATE(enum_name, ...)	\
	MAKE_ENUM(enum_name, __VA_ARGS__)	\
	MAKE_OPERATOR(enum_name, __VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#endif // ENUMERATE_H</span></pre></td></tr></table></div>


<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code70'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39370"><td class="code" id="p393code70"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// test.cpp</span>
&nbsp;
<span style="color: #339900;">#include &quot;Enumerate.h&quot;</span>
&nbsp;
ENUMERATE<span style="color: #008000;">&#40;</span>MonEnumeration,
	E_VAL_1,
	E_VAL_2,
	E_VAL_3<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Après un appel au préprocesseur par "cpp test.cpp", voici ce qu'il nous affiche (remis en forme pour être lisible et<br />
en enlevant les lignes commençant par un #, sans importance) :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code71'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39371"><td class="code" id="p393code71"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">enum</span> MonEnumeration <span style="color: #008000;">&#123;</span> E_VAL_1, E_VAL_2, E_VAL_3 <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">inline</span> std<span style="color: #008080;">::</span><span style="color: #007788;">ostream</span><span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">&lt;&lt;</span><span style="color: #008000;">&#40;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">ostream</span><span style="color: #000040;">&amp;</span> os, <span style="color: #0000ff;">const</span> MonEnumeration<span style="color: #000040;">&amp;</span> e<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">switch</span><span style="color: #008000;">&#40;</span>e<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">case</span> E_VAL_1<span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;E_VAL_1&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> E_VAL_2<span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;E_VAL_2&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> E_VAL_3<span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;E_VAL_3&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> <span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> <span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> <span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> <span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> <span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> <span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> <span style="color: #008080;">:</span> os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">return</span> os<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Vous voyez le problème : on a des "case :" à partir du stade où il n'y a plus d'argument. Il faut donc remplacer<br />
chaque ligne "case ..." (correspondant à ce que génère ENUM_CASE_1) par quelque chose qui puisse faire un test d'égalité<br />
entre "e" et "E_VAL_1", "E_VAL_2"...etc, mais qui puisse aussi compiler et ne rien faire lorsqu'en lieu et place<br />
de "E_VAL_XXX", il n'y a rien.</p>
<p>Là, on pense à la surcharge de fonction ! En effet, si l'on a une fonction surchargée ainsi :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code72'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39372"><td class="code" id="p393code72"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> f<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #666666;">// blabla</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">void</span> f<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #666666;">// blublu</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>on peut obtenir un comportement différent selon que l'on passe ou pas quelque chose en argument à la fonction !<br />
Il suffirait de remplacer chaque ligne "case ..." par un test d'égalité qui aurait cette forme :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code73'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39373"><td class="code" id="p393code73"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>TestEgalite<span style="color: #008000;">&#40;</span>e, E_VAL_1<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;E_VAL_1&quot;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">return</span> os<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>et le tour est joué !</p>
<p>Mais attendez, vous ne voyez pas un problème ? Si, si : contrairement à la fonction f() de l'exemple, ce "TestEgalite"<br />
a 2 arguments. Si l'on remplace "E_VAL_1" par du vide, on obtient un "if(TestEgalite(e, )) {blabla;}" : ça ne marche pas !</p>
<p>Le problème reste donc entier...<br />
Oui, pour ceux qui se demandent, cette partie de l'article n'apporte rien à la solution, c'est juste la démarche que j'ai<br />
eue : vous pouvez vous dire que ça ne sert à rien, je ne vous le reprocherai pas, mais maintenant c'est trop tard, vous<br />
l'avez lu :p</p>
<p>On pourrait se poser le problème ainsi : comment, à partir d'une fonction à 2 arguments, en faire 2 fonctions à 1 argument ?<br />
En effet, si l'on arrive à en faire 2 fonctions à 1 argument, alors le problème serait réglé <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Si je ne m'abuse, il<br />
s'agit de la "curryfication", que l'on trouve en programmation fonctionnelle et en lambda-calcul <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Peut-être est-ce possible, je n'ai pas exploré cette possibilité. Il ne m'étonnerait pas que cela soit possible grâce à des<br />
foncteurs, i.e. une classe dont un surcharge l'opérateur "()". On peut ainsi se retrouver avec une construction de la forme<br />
"MaClasse(arg1)(arg2)", i.e. un appel au constructeur suivi d'un appel à l'opérateur "()".</p>
<p>En fait, à mon avis, c'est une solution possible, je garderai peut-être pour la suite, dans un hypothétique futur article <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Quoi qu'il en soit, pour en revenir au problème : on peut aussi se le poser ainsi : est-on obligés de traiter les cas où<br />
le préprocesseur ne met rien, en lieu et place de nos "E_VAL_1", "E_VAL_2"...etc ? Dit encore autrement, ne peut-on pas mettre<br />
quelque chose d'autre à la place ? Qu'est-ce qui nous arrangerait alors ?</p>
<p>Hmm, voyons voir, remplacer le vide par quelque chose que l'on pourrait tester lors de la compilation...<br />
Il s'agit bien de méta-programmation. Or, en méta-programmation : les 2 outils principaux que le C++ met à notre disposition<br />
sont les macros et les templates.</p>
<p>Eurêka !</p>
<p>On peut "surcharger" une fonction template qui s'occupera de faire le test d'égalité !<br />
On écrit alors les tests d'égalité comme ceci :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code74'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39374"><td class="code" id="p393code74"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>TestEgalite<span style="color: #000080;">&lt;</span>E_VAL_1<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>e<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>blabla<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>TestEgalite<span style="color: #000080;">&lt;</span>E_VAL_2<span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>e<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>blabla<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span>
...
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>TestEgalite<span style="color: #000080;">&lt;</span><span style="color: #0000ff;">void</span><span style="color: #000080;">&gt;</span><span style="color: #008000;">&#40;</span>e<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>blabla<span style="color: #008080;">;</span><span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>On déclare alors TestEgalite sous cette forme :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code75'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39375"><td class="code" id="p393code75"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span>MonEnumeration val<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">bool</span> TestEgalite<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> EnumType<span style="color: #000040;">&amp;</span> e<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">return</span> e <span style="color: #000080;">==</span> val<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> T<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">bool</span> TestEgalite<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> EnumType<span style="color: #000040;">&amp;</span> e<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Et le tour est joué !</p>
<p>Bon, maintenant, pour faire plus pro, en renommant ça en anglais et en préfixant par le nom de l'énumération<br />
(histoire que l'on n'ait pas de conflit s'il y a 2 énumérations différentes, au cas où), et en remettant tout<br />
ensemble, cela donne ceci :</p>
<p>Version finale :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code76'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39376"><td class="code" id="p393code76"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// Enumerate.h</span>
&nbsp;
<span style="color: #339900;">#ifndef ENUMERATE_H</span>
<span style="color: #339900;">#define ENUMERATE_H</span>
&nbsp;
<span style="color: #339900;">#define MAKE_ENUM(EnumType, ...)	\
	enum EnumType { __VA_ARGS__ };</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_1(EnumType, val, ...)	\
	if(EnumType ## _EnumIsEqual&lt;val&gt;(e)) {os &lt;&lt; #val; break;}</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_2(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_1(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_3(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_2(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_4(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_3(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_5(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_4(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_6(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_5(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_7(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_6(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_8(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_7(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_9(EnumType, val, ...)		ENUM_CASE_1(EnumType, val) ENUM_CASE_8(EnumType, __VA_ARGS__, void)</span>
<span style="color: #339900;">#define ENUM_CASE_10(EnumType, val, ...)	ENUM_CASE_1(EnumType, val) ENUM_CASE_9(EnumType, __VA_ARGS__, void)</span>
&nbsp;
<span style="color: #339900;">#define MAKE_OPERATOR(EnumType, ...)	\
	template &lt;EnumType val&gt;				\
	inline bool EnumType ## _EnumIsEqual(const EnumType&amp; e) {	\
		return e == val;										\
	}															\
																\
	template &lt;class T&gt;											\
	inline bool EnumType ## _EnumIsEqual(const EnumType&amp; e) {	\
		return false;											\
	}															\
																\
	inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const EnumType&amp; e) {	\
		do {																\
			ENUM_CASE_10(EnumType, __VA_ARGS__, void)								\
		} while(0);											\
		return os;											\
	}</span>
&nbsp;
<span style="color: #339900;">#define ENUMERATE(EnumType, ...)		\
	MAKE_ENUM(EnumType, __VA_ARGS__)	\
	MAKE_OPERATOR(EnumType, __VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#endif // ENUMERATE_H</span></pre></td></tr></table></div>


<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code77'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39377"><td class="code" id="p393code77"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// main.cpp</span>
&nbsp;
<span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &quot;Enumerate.h&quot;</span>
&nbsp;
ENUMERATE<span style="color: #008000;">&#40;</span>MonEnumeration,
	E_VAL_1,
	E_VAL_2,
	E_VAL_3<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	MonEnumeration e <span style="color: #000080;">=</span> E_VAL_1<span style="color: #008080;">;</span>
	std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> e <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Voilà pour cette partie <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Ceci dit, un problème est résolu, mais il en reste d'autres, notamment :<br />
- ça doit toujours aussi mal passer auprès des systèmes d'auto-complétion (enfin, j'ai pas testé sur Visual Assist<br />
  ou Eclipse à vrai dire...)<br />
- on ne peut toujours pas attribuer de valeur numérique manuellement à un symbole de l'énumération</p>
<p>Il pourrait aussi être intéressant d'associer une autre chaîne de caractères, voire toute autre valeur, à un symbole de<br />
l'énumération...<br />
Tout comme il serait intéressant d'explorer une solution à base de pseudo-curryfication plutôt que de templates, voire, qui<br />
sait, une solution entièrement à base de templates. A ce sujet, un article très intéressant est disponible ici pour les<br />
curieux : http://www.codeguru.com/cpp/cpp/cpp_mfc/templates/article.php/c4137</p>
<p>Ce sera tout pour cette fois !</p>
<p>-------------<br />
EDIT</p>
<p>Petite édition du post original : un pote m'a proposé une petite amélioration du code original (Jérémie, si tu me lis ^^), qui rend le code plus clair et évite de passer par les templates.</p>
<p>L'idée est dans l'opérateur "<<" de créer un objet wrapper autour de ma valeur d'énumération, muni de fonctions de test d'égalité surchargées afin d'accepter un ou zéro argument.<br />
Grâce à cette surcharge, on peut ainsi éviter de traîner les "void" utilisés en paramètres des templates, ce qui est quand même plus propre, et qui encore une fois si le compilateur optimise bien, ne devrait pas créer de différence <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Trève de discours, voici la version finale du code :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p393code78'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p39378"><td class="code" id="p393code78"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// Enumerate.h</span>
&nbsp;
<span style="color: #339900;">#ifndef ENUMERATE_H</span>
<span style="color: #339900;">#define ENUMERATE_H</span>
&nbsp;
<span style="color: #339900;">#define MAKE_ENUM(enum_name, ...)	\
	enum enum_name { __VA_ARGS__ };</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_1(val)	\
	if(s.isEqual(val))		\
		os &lt;&lt; #val;</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_2(val, ...)	ENUM_CASE_1(val) ENUM_CASE_1(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_3(val, ...)	ENUM_CASE_1(val) ENUM_CASE_2(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_4(val, ...)	ENUM_CASE_1(val) ENUM_CASE_3(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_5(val, ...)	ENUM_CASE_1(val) ENUM_CASE_4(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_6(val, ...)	ENUM_CASE_1(val) ENUM_CASE_5(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_7(val, ...)	ENUM_CASE_1(val) ENUM_CASE_6(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_8(val, ...)	ENUM_CASE_1(val) ENUM_CASE_7(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_9(val, ...)	ENUM_CASE_1(val) ENUM_CASE_8(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_10(val, ...)	ENUM_CASE_1(val) ENUM_CASE_9(__VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#define MAKE_OPERATOR(enum_name, ...)	\
	inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const enum_name&amp; e)	{\
		struct {							\
			enum_name e;					\
			inline bool isEqual(enum_name val) const {return e == val;}	\
			inline bool isEqual() const {return false;}					\
		} s;														\
		s.e = e;			\
		ENUM_CASE_10(__VA_ARGS__)	\
		return os;	\
	}</span>
&nbsp;
&nbsp;
<span style="color: #339900;">#define ENUMERATE(enum_name, ...)	\
	MAKE_ENUM(enum_name, __VA_ARGS__)	\
	MAKE_OPERATOR(enum_name, __VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#endif // ENUMERATE_H</span></pre></td></tr></table></div>

<p>Et voilà !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coder-studio.com/blog/preprocesseur-et-enumerations-la-suite/feed/</wfw:commentRss>
		<slash:comments>2710</slash:comments>
		</item>
		<item>
		<title>Faire un peu joujou avec le préprocesseur...</title>
		<link>http://www.coder-studio.com/blog/preproc/</link>
		<comments>http://www.coder-studio.com/blog/preproc/#comments</comments>
		<pubDate>Tue, 14 Jul 2009 18:53:54 +0000</pubDate>
		<dc:creator>Funto</dc:creator>
				<category><![CDATA[C & C++]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[énumération]]></category>
		<category><![CDATA[préprocesseur]]></category>

		<guid isPermaLink="false">http://www.coder-studio.com/blog/?p=371</guid>
		<description><![CDATA[Ça faisait un bail que je n'écrivais pas sur Coder-Studio...
Chose réparée :)

Du 17 au 19 avril 2009, a eu lieu la finale de Cod'INSA, un concours de programmation inter-INSA,
qui s'est déroulée à l'INSA de Toulouse (plus d'infos sur http://codinsa.insa-lyon.fr pour les intéressés).
Faisant partie des organisateurs, j'ai eu à faire l'interfaçage C++/Java (oui parce qu'il y en a qui veulent
participer en Java...allez comprendre :p [/troll]). J'y ai découvert les joies de GCJ et de CNI, ce qui
pourra peut-être être l'objet d'un autre article, selon ma motivation...

Bref, tout ça pour dire qu'il m'a fallu interfacer une librairie écrite en C avec du Java, et qu'il a fallu
automatiser un peu le boulot pour la partie concernant les énumérations.

Dans cet article, je vais illustrer une méthode pour faciliter l'affichage des valeurs des énumérations.
En gros, le but, c'est que si l'on a :
<pre lang="cpp">
MonEnumeration e = E_VAL_1;
std::cout << e << std::endl;
</pre>

il s'affiche alors à l'écran "E_VAL_1".]]></description>
			<content:encoded><![CDATA[<p>Ça faisait un bail que je n'écrivais pas sur Coder-Studio...<br />
Chose réparée <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Du 17 au 19 avril 2009, a eu lieu la finale de Cod'INSA, un concours de programmation inter-INSA,<br />
qui s'est déroulée à l'INSA de Toulouse (plus d'infos sur http://codinsa.insa-lyon.fr pour les intéressés).<br />
Faisant partie des organisateurs, j'ai eu à faire l'interfaçage C++/Java (oui parce qu'il y en a qui veulent<br />
participer en Java...allez comprendre :p [/troll]). J'y ai découvert les joies de GCJ et de CNI, ce qui<br />
pourra peut-être être l'objet d'un autre article, selon ma motivation...</p>
<p>Bref, tout ça pour dire qu'il m'a fallu interfacer une librairie écrite en C avec du Java, et qu'il a fallu<br />
automatiser un peu le boulot pour la partie concernant les énumérations.</p>
<p>Dans cet article, je vais illustrer une méthode pour faciliter l'affichage des valeurs des énumérations.<br />
En gros, le but, c'est que si l'on a :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code79'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37179"><td class="code" id="p371code79"><pre class="cpp" style="font-family:monospace;">MonEnumeration e <span style="color: #000080;">=</span> E_VAL_1<span style="color: #008080;">;</span>
std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> e <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>il s'affiche alors à l'écran "E_VAL_1".</p>
<p><span id="more-371"></span></p>
<p>La version non automatisée consiste en l'écriture d'une surcharge de l'opérateur "<<". Programme de démonstration :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code80'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37180"><td class="code" id="p371code80"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &quot;Enumerate.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">enum</span> MonEnumeration
<span style="color: #008000;">&#123;</span>
	E_VAL_1,
	E_VAL_2
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
std<span style="color: #008080;">::</span><span style="color: #007788;">ostream</span><span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">&lt;&lt;</span><span style="color: #008000;">&#40;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">ostream</span><span style="color: #000040;">&amp;</span> os, <span style="color: #0000ff;">const</span> MonEnumeration<span style="color: #000040;">&amp;</span> e<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">switch</span><span style="color: #008000;">&#40;</span>e<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">case</span> E_VAL_1<span style="color: #008080;">:</span>
		os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;E_VAL_1&quot;</span><span style="color: #008080;">;</span>
		<span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">case</span> E_VAL_2<span style="color: #008080;">:</span>
		os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #FF0000;">&quot;E_VAL_2&quot;</span><span style="color: #008080;">;</span>
		<span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
	<span style="color: #0000ff;">return</span> os<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	MonEnumeration e <span style="color: #000080;">=</span> E_VAL_1<span style="color: #008080;">;</span>
	std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> e <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Ce programme affiche bien "E_VAL_1" à l'écran.</p>
<p>Mais c'est tout de même bien contraignant : la duplication des informations est évidente : entre la<br />
déclaration de l'énumération et l'opérateur "<<", "E_VAL_1" est écrit 3 fois ! C'est évidemment source<br />
d'erreurs (le copier-coller n'est pas le meilleur ami du programmeur, loin s'en faut...), particulièrement<br />
lorsque l'on veut rajouter de nouvelles valeurs à l'énumération. Et puis c'est tout simplement pénible<br />
de devoir maintenir l'énumération et l'opérateur.<br />
Bref, c'est moche, peut mieux faire.</p>
<p>C'est là qu'arrive le préprocesseur.</p>
<p>A partir de là, je suppose que vous utilisez GCC (ou MinGW/Cygwin sous Windows).</p>
<p>Nous allons en particulier nous baser sur 2 opérateurs spéciaux du préprocesseur, qui ne sont pas très<br />
connus : # et ##.</p>
<p>Commençons par # : il permet de rajouter des guillemets autour de l'argument d'une macro.</p>
<p>Démonstration :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code81'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37181"><td class="code" id="p371code81"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define STRINGIFY(val) #val</span>
&nbsp;
STRINGIFY<span style="color: #008000;">&#40;</span>pouet<span style="color: #008000;">&#41;</span></pre></td></tr></table></div>

<p>Supposons que vous ayez enregistré cela dans "pouet.h" : passez un coup de préprocesseur : "cpp pouet.h"<br />
(ou bien "g++ -E pouet.h", ça revient au même).</p>
<p>Résultat affiché :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code82'); return false;">View Code</a> TEXT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37182"><td class="code" id="p371code82"><pre class="text" style="font-family:monospace;"># 1 &quot;pouet.h&quot;
# 1 &quot;&lt;interne&gt;&quot;
# 1 &quot;&lt;command-line&gt;&quot;
# 1 &quot;pouet.h&quot;
&nbsp;
&nbsp;
&quot;pouet&quot;</pre></td></tr></table></div>

<p>Bon, déjà, ça c'est intéressant <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  On remarque que cpp écrit des lignes commençant par un #, que le compilateur<br />
qui passe derrière doit probablement interpréter pour les messages d'erreurs afin d'indiquer la ligne de l'erreur.</p>
<p>Passons à la suite : on voudrait une macro qui permette d'automatiser la création de l'opérateur "<<" pour<br />
l'affichage de la valeur de notre énumération.<br />
Essayons d'abord en supposant que notre énumération ne puisse contenir qu'une seule valeur :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code83'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37183"><td class="code" id="p371code83"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define MAKE_ENUM(enum_name, val)	\
	enum enum_name {	\
		val			\
	};</span>
&nbsp;
<span style="color: #339900;">#define MAKE_OPERATOR(enum_name, val)	\
	inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const enum_name&amp; e)	{\
		switch(e) {	\
			case val:	\
				os &lt;&lt; #val;	\
				break;	\
		}	\
		return os;	\
	}</span>
&nbsp;
&nbsp;
<span style="color: #339900;">#define ENUMERATE(enum_name, val)	\
	MAKE_ENUM(enum_name, val)	\
	MAKE_OPERATOR(enum_name, val)</span>
&nbsp;
ENUMERATE<span style="color: #008000;">&#40;</span>MonEnumeration,
	E_VAL_1<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>On a donc une macro MAKE_ENUM qui s'occupe de déclarer l'énumération et une macro MAKE_OPERATOR qui s'occupe<br />
de définir l'operateur "<<". Notez le "inline" qui sert à éviter tout problème de linkage (si le même fichier .h,<br />
qui décrit l'énumération et l'opérateur, est inclus dans 2 .cpp différents, on se retrouve avec l'opérateur défini 2<br />
fois, et couic !).</p>
<p>Cool, ça marche ! (en même temps c'est un tuto...)</p>
<p>Maintenant, on peut arrêter de contourner la difficulté et s'attaquer au vrai problème : comment gérer le fait<br />
qu'une énumération n'ai pas 1, 2, ou 3 valeurs, mais un nombre variable ??</p>
<p>C'est là qu'arrive une autre astuce du préprocesseur : la macro __VA_ARGS__.</p>
<p>Démonstration, dans notre pouet.h :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code84'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37184"><td class="code" id="p371code84"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define MA_MACRO(...) __VA_ARGS__</span>
MA_MACRO<span style="color: #008000;">&#40;</span>a, b, c<span style="color: #008000;">&#41;</span></pre></td></tr></table></div>

<p>cpp pouet.h donne :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code85'); return false;">View Code</a> TEXT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37185"><td class="code" id="p371code85"><pre class="text" style="font-family:monospace;"># 1 &quot;pouet.h&quot;
# 1 &quot;&lt;interne&gt;&quot;
# 1 &quot;&lt;command-line&gt;&quot;
# 1 &quot;pouet.h&quot;
&nbsp;
a, b, c</pre></td></tr></table></div>

<p>Pratique, quand on veut des macros avec un nombre variable d'arguments...</p>
<p>On peut dores et déjà remplacer MAKE_ENUM par une version capable de gérer un nombre variable d'arguments :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code86'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37186"><td class="code" id="p371code86"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define MAKE_ENUM(enum_name, ...)	\
	enum enum_name { __VA_ARGS__ };</span></pre></td></tr></table></div>

<p>Ça, c'est fait. Maintenant, reste le problème de MAKE_OPERATOR...</p>
<p>Si l'on analyse le problème, on voit que l'on a 3 parties :</p>
<p>- une introduction :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code87'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37187"><td class="code" id="p371code87"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">inline</span> std<span style="color: #008080;">::</span><span style="color: #007788;">ostream</span><span style="color: #000040;">&amp;</span> operator<span style="color: #000080;">&lt;&lt;</span><span style="color: #008000;">&#40;</span>std<span style="color: #008080;">::</span><span style="color: #007788;">ostream</span><span style="color: #000040;">&amp;</span> os, <span style="color: #0000ff;">const</span> enum_name<span style="color: #000040;">&amp;</span> e<span style="color: #008000;">&#41;</span>	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000ff;">switch</span><span style="color: #008000;">&#40;</span>e<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span></pre></td></tr></table></div>

<p>- une partie qui se répète :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code88'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37188"><td class="code" id="p371code88"><pre class="cpp" style="font-family:monospace;">		<span style="color: #0000ff;">case</span> val<span style="color: #008080;">:</span>
			os <span style="color: #000080;">&lt;&lt;</span> <span style="color: #339900;">#val;</span>
			<span style="color: #0000ff;">break</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>- une conclusion :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code89'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37189"><td class="code" id="p371code89"><pre class="cpp" style="font-family:monospace;">		<span style="color: #008000;">&#125;</span>
		<span style="color: #0000ff;">return</span> os<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Il s'agit donc, à partir d'une liste variable d'arguments, de répéter plusieurs fois la partie centrale pour<br />
chaque argument "val". C'est là que j'ai pensé à ces vieux cours de Caml, où pour traiter une liste, on écrivait<br />
une fonction récursive, qui décomposait la liste en t::q (pour tête et queue), la tête étant le 1er élément, et la<br />
queue tout le reste. Désolé pour ceux qui n'ont pas fait de Caml :p</p>
<p>Pour revenir à notre préprocesseur, cela se traduirait par une macro qui prend en argument quelque chose de la forme :<br />
#define MACRO(a, ...) et qui ensuite s'appellerait récursivement jusqu'à ce qu'il n'y ait plus d'argument.</p>
<p>Malheureusement, la récursivité, en préprocesseur ça n'existe pas, ou alors j'ai pas trouvé comment...</p>
<p>Il va donc falloir trouver une parade : il s'agira d'écrire une version de la macro pour chaque appel récursif, i.e.<br />
pour chaque nombre d'arguments :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code90'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37190"><td class="code" id="p371code90"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define ENUM_CASE_1(val)	\
	case val:	\
		os &lt;&lt; #val;	\
		break;</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_2(val, ...)	ENUM_CASE_1(val) ENUM_CASE_1(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_3(val, ...)	ENUM_CASE_1(val) ENUM_CASE_2(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_4(val, ...)	ENUM_CASE_1(val) ENUM_CASE_3(__VA_ARGS__)</span></pre></td></tr></table></div>

<p>Le problème n'est toujours pas totalement résolu : encore faut-il choisir la bonne macro à utiliser...</p>
<p>C'est là qu'arrive l'opérateur ## du préprocesseur <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Celui-ci permet de concaténer des symboles.</p>
<p>Exemple (dans pouet.h) :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code91'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37191"><td class="code" id="p371code91"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define CONCAT(a, b) a ## b</span>
CONCAT<span style="color: #008000;">&#40;</span>foo, bar<span style="color: #008000;">&#41;</span></pre></td></tr></table></div>

<p>"cpp pouet.h" affiche cette fois :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code92'); return false;">View Code</a> TEXT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37192"><td class="code" id="p371code92"><pre class="text" style="font-family:monospace;"># 1 &quot;pouet.h&quot;
# 1 &quot;&lt;interne&gt;&quot;
# 1 &quot;&lt;command-line&gt;&quot;
# 1 &quot;pouet.h&quot;
&nbsp;
foobar</pre></td></tr></table></div>

<p>Cela va nous servir à choisir la bonne macro à utiliser :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code93'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37193"><td class="code" id="p371code93"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define ENUM_CASE_N(nb_vals, ...) ENUM_CASE_ ## nb_vals(__VA_ARGS__)</span></pre></td></tr></table></div>

<p>Le gros inconvénient est bien sûr qu'il nous faut préciser le nombre de valeurs de l'énumération :/</p>
<p>Il semble que l'on ait fait le tour. Voici donc la version finale de tout ça, séparée dans un .h générique<br />
et un .cpp d'exemple :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code94'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37194"><td class="code" id="p371code94"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// Enumerate.h</span>
&nbsp;
<span style="color: #339900;">#ifndef ENUMERATE_H</span>
<span style="color: #339900;">#define ENUMERATE_H</span>
&nbsp;
<span style="color: #339900;">#define MAKE_ENUM(enum_name, ...)	\
	enum enum_name { __VA_ARGS__ };</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_1(val)	\
	case val:	\
		os &lt;&lt; #val;	\
		break;</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_2(val, ...)	ENUM_CASE_1(val) ENUM_CASE_1(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_3(val, ...)	ENUM_CASE_1(val) ENUM_CASE_2(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_4(val, ...)	ENUM_CASE_1(val) ENUM_CASE_3(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_5(val, ...)	ENUM_CASE_1(val) ENUM_CASE_4(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_6(val, ...)	ENUM_CASE_1(val) ENUM_CASE_5(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_7(val, ...)	ENUM_CASE_1(val) ENUM_CASE_6(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_8(val, ...)	ENUM_CASE_1(val) ENUM_CASE_7(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_9(val, ...)	ENUM_CASE_1(val) ENUM_CASE_8(__VA_ARGS__)</span>
<span style="color: #339900;">#define ENUM_CASE_10(val, ...)	ENUM_CASE_1(val) ENUM_CASE_9(__VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#define ENUM_CASE_N(nb_vals, ...) ENUM_CASE_ ## nb_vals(__VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#define MAKE_OPERATOR(nb_vals, enum_name, ...)	\
	inline std::ostream&amp; operator&lt;&lt;(std::ostream&amp; os, const enum_name&amp; e)	{\
		switch(e) {	\
			ENUM_CASE_N(nb_vals, __VA_ARGS__)	\
		}	\
		return os;	\
	}</span>
&nbsp;
&nbsp;
<span style="color: #339900;">#define ENUMERATE(nb_vals, enum_name, ...)	\
	MAKE_ENUM(enum_name, __VA_ARGS__)	\
	MAKE_OPERATOR(nb_vals, enum_name, __VA_ARGS__)</span>
&nbsp;
<span style="color: #339900;">#endif // ENUMERATE_H</span></pre></td></tr></table></div>


<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p371code95'); return false;">View Code</a> CPP</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p37195"><td class="code" id="p371code95"><pre class="cpp" style="font-family:monospace;"><span style="color: #666666;">// main.cpp</span>
&nbsp;
<span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &quot;Enumerate.h&quot;</span>
&nbsp;
ENUMERATE<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">3</span>, MonEnumeration,
	E_VAL_1,
	E_VAL_2,
	E_VAL_3<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	MonEnumeration e <span style="color: #000080;">=</span> E_VAL_1<span style="color: #008080;">;</span>
	std<span style="color: #008080;">::</span><span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;&lt;</span> e <span style="color: #000080;">&lt;&lt;</span> std<span style="color: #008080;">::</span><span style="color: #007788;">endl</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p><strong>Conclusion</strong></p>
<p>Au final, cette méthode présente l'avantage d'éviter la duplication de code, et tous les ennuis qui vont avec.<br />
Il reste cependant plusieurs inconvénients non négligeables :<br />
- On est obligés de préciser le nombre de valeurs de l'énumération<br />
- On est limités dans le nombre de valeurs que l'on peut définir par le nombre de macros que l'on a définis dans Enumerate.h<br />
  A la limite, si l'on a besoin de plus de valeurs, il suffit de les rajouter, c'est pas bien grave ^^<br />
- Pour la plupart des IDE, je pense qu'un tel système aboutit à un type "MonEnumeration", ainsi que les valeurs définies,<br />
  qui sont inconnus. Ça peut être un problème...<br />
- En déclarant ses énumérations de la sorte, on ne peut pas préciser de valeur numérique pour chaque valeur possible de<br />
  l'énumération.</p>
<p>La méthode a ses limites, et je me demande s'il n'y aurait pas moyen d'aller au-delà en utilisant des templates...<br />
Par ailleurs, ce petit article sur le préprocesseur ne fait aucune mention de Boost::Preprocessor, qui, selon Arnaud,<br />
est incroyable à voir...<br />
Je serais curieux de voir s'il pourrait apporter un élément de réponse au problème ^^</p>
<p>Ce sera tout !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coder-studio.com/blog/preproc/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>GTK+ en Haskell</title>
		<link>http://www.coder-studio.com/blog/gtk-en-haskell/</link>
		<comments>http://www.coder-studio.com/blog/gtk-en-haskell/#comments</comments>
		<pubDate>Tue, 16 Jun 2009 02:37:15 +0000</pubDate>
		<dc:creator>Alp Mestan</dc:creator>
				<category><![CDATA[Langages fonctionnels]]></category>
		<category><![CDATA[glade]]></category>
		<category><![CDATA[gtk]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.coder-studio.com/blog/?p=342</guid>
		<description><![CDATA[Bonjour, M'étant mis à Haskell depuis quelques temps (principalement grâce au désormais fameux Real World Haskell), je me suis dis qu'il était temps que je regarde un peu du côté des bibliothèques pour interfaces utilisateurs. Hé bien, je n'ai pas été déçu. Il y a notamment Gtk2Hs qui fournit un bon binding de GTK+, compatible [...]]]></description>
			<content:encoded><![CDATA[<p>Bonjour,</p>
<p>M'étant mis à Haskell depuis quelques temps (principalement grâce au désormais fameux <a href="http://general.developpez.com/livres/general/?page=prog-fonctionnelle#L9780596514983">Real World Haskell</a>), je me suis dis qu'il était temps que je regarde un peu du côté des bibliothèques pour interfaces utilisateurs. Hé bien, je n'ai pas été déçu. Il y a notamment <strong>Gtk2Hs</strong> qui fournit un bon binding de GTK+, compatible avec Glade (le designer) et qui permet donc de charger des interfaces depuis du XML.</p>
<p><center><img src="http://blog.developpez.com/media/gtk2hs.png" width="409" height="297" alt="Gtk2Hs en action" /></center></p>
<p><span id="more-342"></span></p>
<p>Allez-y, devinez combien de lignes il a fallu ?<br />
Initialiser le GUI, créer les widgets, ... Hmm beaucoup ?</p>
<p>Hé bien non ! Le designer, Glade, exporte le "projet" suivant dans un XML.</p>
<p><center><img src="http://blog.developpez.com/media/glade.png" width="700" height="370" alt="Designer de fenêtres de GTK+" /></center></p>
<p>XML généré :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p342code98'); return false;">View Code</a> XML</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p34298"><td class="code" id="p342code98"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span> 
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;glade-interface<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
  <span style="color: #808080; font-style: italic;">&lt;!-- interface-requires gtk+ 2.16 --&gt;</span> 
  <span style="color: #808080; font-style: italic;">&lt;!-- interface-naming-policy project-wide --&gt;</span> 
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;widget</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;GtkWindow&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;window1&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span> 
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;title&quot;</span> <span style="color: #000066;">translatable</span>=<span style="color: #ff0000;">&quot;yes&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Hello, Developpez !<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;default_width&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>400<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;default_height&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>400<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;child<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;widget</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;GtkButton&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;yo&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span> 
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;label&quot;</span> <span style="color: #000066;">translatable</span>=<span style="color: #ff0000;">&quot;yes&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Bonjour Developpez, comment vas-tu ? 
&nbsp;
Je suis un programme Haskell qui utilise 
Gtk2Hs, binding Haskell de GTK+. 
&nbsp;
Clique pour fermer.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;visible&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>True<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;can_focus&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>True<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;receives_default&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>True<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/widget<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/child<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/widget<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/glade-interface<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Et voilà, l'essentiel est fait.</p>
<p>Voici donc le main.hs, qui est le programme Haskell dont vous avez vu un screenshot plus haut :</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p342code99'); return false;">View Code</a> HASKELL</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p34299"><td class="code" id="p342code99"><pre class="haskell" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">module</span> Main <span style="color: #06c; font-weight: bold;">where</span> 
&nbsp;
<span style="color: #06c; font-weight: bold;">import</span> Graphics<span style="color: #339933; font-weight: bold;">.</span>UI<span style="color: #339933; font-weight: bold;">.</span>Gtk <span style="color: #5d478b; font-style: italic;">-- on importe le module GTK </span>
<span style="color: #06c; font-weight: bold;">import</span> Graphics<span style="color: #339933; font-weight: bold;">.</span>UI<span style="color: #339933; font-weight: bold;">.</span>Gtk<span style="color: #339933; font-weight: bold;">.</span>Glade <span style="color: #5d478b; font-style: italic;">-- et le module Glade, pour créer une IHM depuis le XML au format Glade </span>
&nbsp;
main <span style="color: #339933; font-weight: bold;">=</span> <span style="color: #06c; font-weight: bold;">do</span> 
  initGUI 
  Just xml <span style="color: #339933; font-weight: bold;">&lt;-</span> xmlNew <span style="background-color: #3cb371;">&quot;test.glade&quot;</span>  
  window <span style="color: #339933; font-weight: bold;">&lt;-</span> xmlGetWidget xml castToWindow <span style="background-color: #3cb371;">&quot;window1&quot;</span> 
  button <span style="color: #339933; font-weight: bold;">&lt;-</span> xmlGetWidget xml castToButton <span style="background-color: #3cb371;">&quot;yo&quot;</span> 
  onClicked button <span style="color: #339933; font-weight: bold;">$</span> <span style="color: #06c; font-weight: bold;">do</span> 
  <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:putStrLn"><span style="font-weight: bold;">putStrLn</span></a> <span style="background-color: #3cb371;">&quot;Bye&quot;</span> 
  mainQuit 
  onDestroy window mainQuit 
  widgetShowAll window 
  mainGUI</pre></td></tr></table></div>

<p>Et voilà. Assez simple non ? <img src='http://www.coder-studio.com/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.coder-studio.com/blog/gtk-en-haskell/feed/</wfw:commentRss>
		<slash:comments>3022</slash:comments>
		</item>
	</channel>
</rss>

