<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="http://blog.mymind.fr/feed/rss2/xslt" ?><rss version="2.0"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>Mind... - Tag - C</title>
  <link>http://blog.mymind.fr/</link>
  <atom:link href="http://blog.mymind.fr/feed/tag/C/rss2" rel="self" type="application/rss+xml"/>
  <description></description>
  <language>fr</language>
  <pubDate>Thu, 01 Dec 2011 21:43:54 +0100</pubDate>
  <copyright>© 2007-2008 Florent Bruneau</copyright>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Dotclear</generator>
  
    
  <item>
    <title>Templates en C</title>
    <link>http://blog.mymind.fr/post/2007/08/16/Templates-en-C</link>
    <guid isPermaLink="false">urn:md5:305c30979642387ee13cea31a6b77855</guid>
    <pubDate>Thu, 16 Aug 2007 22:53:00 +0200</pubDate>
    <dc:creator>Florent Bruneau</dc:creator>
        <category>GeekTime</category>
        <category>C</category><category>Cpp</category><category>Devel</category>    
    <description>&lt;p&gt;En C++, il existe un mécanisme extrêmement pratique pour généré du code générique&amp;nbsp;: les templates. Une fonction templatée est une fonction dont le code comporte un trou qui sera remplacé à la compilation par le nom d'un type, ou une valeur... Par exemple&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
template &amp;lt;class T&amp;gt; 
T read(const char *buffer) 
{
    T val;
    memcpy(&amp;amp;val, buffer, sizeof(T));
    return val;
} 
&lt;/pre&gt;


&lt;p&gt;Cette fonction lit un objet de type T sur un buffer. L'intérêt de cette fonction est très compréhensible&amp;nbsp;: quel que soit le type qu'on fournit à la fonction, elle va fonctionner, en adaptant la taille à lire au type. C'est donc beaucoup plus rapide que d'écrire une fonction pour chaque type... et l'utilisation est également très simple&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
read&amp;lt;int&amp;gt;(const char* buffer) // lit un entier sur le buffer
read&amp;lt;double&amp;gt;(const char* buffer) // lit un double sur le buffer
read&amp;lt;MaClass&amp;gt;(const char* buffer) // lit un objet de type &amp;quot;MaClass&amp;quot;
&lt;/pre&gt;


&lt;p&gt;Mais cette syntaxe n'est qu'un sucre syntaxique, car en fait, on peut également faire des templates en C...&lt;/p&gt;    &lt;h3&gt;Comment fonctionne les templates&amp;nbsp;?&lt;/h3&gt;


&lt;p&gt;En fait un template est, comme son nom l'indique, qu'un modèle de fonction. Lors de la compilation d'un programme qui utilise des templates, le compilateur regarde la liste des instances de cette fonction qui sont utilisées et les génère. Plus explicitement, si j'appelle read&amp;lt;double&amp;gt;(), le compilateur va générer cette fonction&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
[cpp]
double read&amp;lt;double&amp;gt;(const char *buffer) 
{
    double val;
    memcpy(&amp;amp;val, buffer, sizeof(double));
    return val;
}
&lt;/pre&gt;


&lt;p&gt;Ainsi, l'appel à read&amp;lt;double&amp;gt; devient un appel de fonction classique.&lt;/p&gt;


&lt;h3&gt;Jeu de préprocesseur&lt;/h3&gt;


&lt;p&gt;Le préprocesseur en C possède des outils sympathique... Nous nous attarderons particulièrement sur le ##. Il s'agit tout simplement d'un opérateur de concaténation. Donc&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
[c]
#define Truc(Machin) Truc ## Machin

Truc(Bidule) /* génère TrucBidule */
&lt;/pre&gt;


&lt;p&gt;C'est donc très pratique. On peut facilement par exemple, imaginer une petite macro du genre&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
[c]
#define maFonction(Type) maFonction_ ## Type
&lt;/pre&gt;


&lt;p&gt;Si dans ce cas, on défini par exemple maFonction_int, maFonction_double, maFonction_MaStruct (oui, les classes n'existent pas en C), on pourra faire&lt;/p&gt;

&lt;pre&gt;
[c]
maFonction(int)(args); /* appelle maFonction_int */
maFonction(double)(args); /* appelle maFonction_double */
maFonction(MaStruct)(args); /* appelle maFonction_MaStruct */
&lt;/pre&gt;


&lt;p&gt;Maintenant, il ne reste plus qu'à générer les fonctions... sans avoir à toutes les écrire une à une. Pour ceci, nous allons encore une fois profiter de la présence du préprocesseur.&lt;/p&gt;

&lt;pre&gt;
[c]
#define maFonctionBuild(Type) \\
  Type maFonction_ ## Type(const char* buffer) { \\
    Type val; \\
    memcpy(&amp;amp;val, buffer, sizeof(Type)); \\
    return val; \\
  } 

maFonctionBuild(int) /* génère maFonction_int */
maFonctionBuild(double) /* génère maFonction_double */
maFonctionBuild(MaStruct) /* génère maFonction_MaStruct */
&lt;/pre&gt;


&lt;p&gt;Il ne reste donc qu'à appeler maFonctionBuild(Type) sur chacun des types pour lesquels nous avons besoin d'instancier la fonction, et d'appeler maFonction(Type) chaque fois qu'on veut appeler maFonction pour le type en question. D'une certaine manière on peut dès lors dire que les fonctions sont&amp;nbsp;:&lt;/p&gt;

&lt;pre&gt;
[c]
Type maFonction(Type)(const char* buffer);
&lt;/pre&gt;


&lt;h3&gt;Et voilà&amp;nbsp;!&lt;/h3&gt;


&lt;p&gt;Nous avons donc une implémentation générique grâce au préprocesseur associé à un appel typé. Ce n'est évidemment qu'une astuce de préprocesseur, mais cela donne une souplesse syntaxique agréalble&amp;nbsp;: &quot;J'appelle maFonction appliquée sur les entiers avec les arguments args&quot;.&lt;/p&gt;


&lt;p&gt;Tout ceci est certes, moins souple que les templates C++&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;il n'y a pas d'auto-instanciation par le compilateur&amp;nbsp;: il faut &quot;manuellement&quot; instancier la fonction pour tous les types pour lesquels ont l'appelle&lt;/li&gt;
&lt;li&gt;il n'y a pas de &quot;type check&quot;&amp;nbsp;: les seules limites sont celle de la compilation&lt;/li&gt;
&lt;li&gt;le correction des erreurs de compilation est fastidieuse car toutes les erreurs apparaissent comme étant à la ligne d'appel à maFonctionBuild&lt;/li&gt;
&lt;li&gt;il est rapidement fastidieux de rajouter l'antislash à la fin de chaque ligne de la définition de la fonction&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Comme on le voit dans les choix de l'exemple, pour les entrées/sorties, ça permet d'avoir une seule fonction à écrire tout en gardant la flexibilité d'une fonction par type de données.&lt;/p&gt;</description>
    
    
    
          <comments>http://blog.mymind.fr/post/2007/08/16/Templates-en-C#comment-form</comments>
      <wfw:comment>http://blog.mymind.fr/post/2007/08/16/Templates-en-C#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.mymind.fr/feed/atom/comments/34</wfw:commentRss>
      </item>
    
  <item>
    <title>Démon pour khtml2png</title>
    <link>http://blog.mymind.fr/post/2007/03/14/Demon-pour-khtml2png</link>
    <guid isPermaLink="false">urn:md5:58e9608d38ac069663e670c212792f8b</guid>
    <pubDate>Wed, 14 Mar 2007 18:24:00 +0100</pubDate>
    <dc:creator>Florent Bruneau</dc:creator>
        <category>Polytechnique.org</category>
        <category>C</category><category>Devel</category><category>khtml2png</category><category>khtmld</category>    
    <description>&lt;p&gt;Une fois qu'on a un outils pour faire les vignettes de site, il devient utile de pouvoir automatiser le travail. Pour ceci, il existe un &lt;a href=&quot;http://wiki.goatpron.de/project/khtmld&quot;&gt;démon pour khtml2png&lt;/a&gt;. Malheureusement (encore une fois), cet outil ne correspondait pas exactement à mes besoins. Donc je l'ai partiellement réécrit (mais rien d'extraordinaire).&lt;/p&gt;    &lt;p&gt;Ce démon qui s'appelle &lt;code&gt;khtmld&lt;/code&gt; fonctionne simplement&amp;nbsp;: il lit une file et à chaque entrée dans cette file, il lance &lt;code&gt;khtml2png&lt;/code&gt;. Donc, il y a deux étapes.&lt;/p&gt;


&lt;p&gt;La première consiste à lancer le démon. Pour ceci, j'ai développé un script d'init... qui sera donc probablement lancé par l'utilisateur &lt;code&gt;root&lt;/code&gt;. Il suffit de modifier ce script pour régler les variables en fonction de son installation, puis dans lancer la commande&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
[bash]
./init-script.sh start
&lt;/pre&gt;


&lt;p&gt;Ensuite il n'y a plus qu'à donner au démon la liste des actions à réaliser sous la forme&lt;sup&gt;[&lt;a href=&quot;http://blog.mymind.fr/post/2007/03/14/Demon-pour-khtml2png#pnote-13-1&quot; id=&quot;rev-pnote-13-1&quot;&gt;1&lt;/a&gt;]&lt;/sup&gt;&amp;nbsp;:&lt;/p&gt;
&lt;pre&gt;
[bash]
echo &amp;quot;url fichier&amp;quot; &amp;gt;&amp;gt; /tmp/khtmld.spool
&lt;/pre&gt;


&lt;p&gt;Le principal développement que j'ai réalisé sur &lt;code&gt;khtmld&lt;/code&gt; permet de donner au processus de &lt;code&gt;khtml2png&lt;/code&gt; les droits d'un utilisateur du choix de la personne qui a lancé le démon (certes rien d'extraordinaire, mais ça manquait au programme).&lt;/p&gt;


&lt;p&gt;Voilà, donc un système pour automatiser la réalisation de vignettes même si il reste quelques points sur lesquels il faut réfléchir&amp;nbsp;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;on ne veut pas un service ouvert (faire un screenshot est une opération lourde)&lt;/li&gt;
&lt;li&gt;on ne peut pas mettre ce service sur un serveur de prod (il est hors de question de lancer un X en production)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Donc il faut s'orienter sur la réalisation d'un serveur de screenshot avec authentification et modération... non-trivial.&lt;/p&gt;


&lt;p&gt;Pour ceux qui voudraient récupérer ma version, elle est disponible dans &lt;a href=&quot;http://blog.mymind.fr/mind/public/khtml2png/khtmld-fru-last.tar.bz2&quot;&gt;les téléchargements&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;&lt;h4&gt;Notes&lt;/h4&gt;
&lt;p&gt;[&lt;a href=&quot;http://blog.mymind.fr/post/2007/03/14/Demon-pour-khtml2png#rev-pnote-13-1&quot; id=&quot;pnote-13-1&quot;&gt;1&lt;/a&gt;] Attention à ne pas mettre d'espace dans le nom du fichier et dans l'url.&lt;/p&gt;&lt;/div&gt;
</description>
    
    
    
          <comments>http://blog.mymind.fr/post/2007/03/14/Demon-pour-khtml2png#comment-form</comments>
      <wfw:comment>http://blog.mymind.fr/post/2007/03/14/Demon-pour-khtml2png#comment-form</wfw:comment>
      <wfw:commentRss>http://blog.mymind.fr/feed/atom/comments/13</wfw:commentRss>
      </item>
    
</channel>
</rss>
