<?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 &#187; Calvin1602</title>
	<atom:link href="http://www.coder-studio.com/blog/author/calvin1602/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.coder-studio.com/blog</link>
	<description></description>
	<lastBuildDate>Wed, 02 Mar 2011 22:17:07 +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>
	</channel>
</rss>

