Ma fille fait des blagues !

Incroyable. Peut-être que beaucoup de parents ne trouveraient pas ça si extraordinaire mais nous venons tout juste d’avoir une bonne crise de fou rire.

Pour les deux ans d’Inès, ma soeur (« tatie Véronique ») lui a acheté « Barbapapa en voyage ».

Dans ce DVD (qui est très bien au passage), il y a à un moment un barbapapa qui va se cacher pour prendre des photos et tous ses frères et soeurs qui se cachent, et lorsque le soir arrive et qu’il veut prendre des photos, ses frères et soeurs sortent et se tranforment en animaux. Alors il les filme et il est tout content, mais il s’aperçoit que ce ne sont pas des animaux et tout le monde éclate de rire. Alors nous avons expliqué à Inès qu’ils lui avaient fait une blague.

Quelques minutes plus tard, Inès se met à quattre patte, et veut jouer avec ses voitures. Elle tombe, et crie « aïe maman je me suis fait mal ». Sandrine, inquiète, lui demande où elle s’est fait mal. Inès la regarde en souriant et lui dit « je t’ai fait une blague maman ! ».

Nous avons eu une bonne crise de rire. Que c’est bon !

Oui, Inès a 26 mois. Je ne sais pas si c’est précoce mais c’est tôt je trouve, pour comprendre le principe de « faire des blagues ».

Excellent !

Librairie Apr : tutoriel 12

12. DSO (Dynamic Symbol Object)

Vous connaissez peut-être les objets partagés (so = shared object) ou les dlls (dll=dynamic link library). Grossièrement on peut dire que DSO est né du principe des so/dll. Mais on parle de dso (Dynamic Symbol Object) pour les différencier des librairies dynamiques so/dll.

Pour comprendre le fonctionnement des dso, il faut savoir comment fonctionne le link et le chargement. En général, lorsqu’on utilise des librairies dynamiques, on les « link » avec le programme principal lors de la compilation. ld(1) s’occupe de cela sur Unix. ld(1) est connu en tant qu’éditeur de lien. Comme ld(1) est habituellement appelé par le compilateur lui-même gcc(1) de façon implicite, peut-être n’avez-vous jamais entendu parler de ld(1). Au mieux avez-vous vu des messages problème de « link » lors de la compilation. Cela signifie que ld(1) n’arrive pas à résoudre certains symboles que vous utilisez dans votre programme. En cours d’exécution, ld.so(8) charge les librairies dynamiques. S’il n’y arrive pas, vous verrez des messages d’erreur de chargement. En résumé, le « link » est fait lors de la compilation, et le chargement est fait lors de l’exécution. Si vous voulez en savoir plus, il vous suffit de lire les manuels ld(1) et ld.so(8).

Grâce à dso, le link et le chargement sont faits lors de l’exécution. Quel est l’intérêt d’un tel mécanisme ? La raison se résume en deux mots : architecture plugin. La seule chose que nous ayons à faire lors de la compilation est de définir les interfaces (« noms symboliques » et la manière les appeler, les paramètres à leur donner, donc) des modules qu’il devra être possible de charger. Le programme charge les modules pendant son exécution, et s’en sert au travers d’interfaces. Les modules dynamiquement « téléchargeables » peuvent ainsi être développés par des programmeurs indépendants. Vous pourrez ainsi rendre votre programme très flexible et extensible.

Voyons voir dso-sample.c. Vous pouvez y voir deux chaines : « libm.so » et « pow ». En réalité, pow(3) est une fonction basique et, en temps normal, n’a pas besoin d’être appelée sous forme de dso, mais c’est simplement pour l’exemple.

Au début, on appelle apr_dso_load() et on lui donne le nom de la librairie : « libm.so ».

/* extrait de dso-sample.c, vérif. des erreurs omise */
const char fname[] = "libm.so";
    apr_dso_handle_t *dso_h;
    apr_dso_load(&dso_h, fname, mp);

Comme vous pouvez l’imaginer, si vous voulez programmer en donnant la possibilité aux autres de faire des plugins pour votre programme, vous devez faire en sorte d’avroi un fichier dans lequel il y a tous les noms des plugins à télécharger. On a déjà quelque chose qui tourne plutôt bien : les modules apache. Leurs noms sont spécifiés, en général, dans le fichier de configuration principal : le fichier « httpd.conf ».

Lorsque apr_dso_load() renvoie une erreur, c’est, la plupart du temps, parce qu’il ne trouve pas le fichier de la librairie dynamique. Le chemin de recherche pour les librairies dépend du système d’exploitation. Sur GNU/Linux, il dépend de la variable d’environnement LD_LIBRARY_PATH. Sur MS-Windows, il dépend de la variable d’environnement PATH. Après avoir un résultat de retour de apr_dso_load() réussi, on peut appeler apr_dso_sym().

Voici le prototype :

/* extrait de apr_dso.h */
APR_DECLARE(apr_status_t) apr_dso_sym(
    apr_dso_handle_sym_t *ressym,
    apr_dso_handle_t *handle,
    const char *symname);

On peut récupérer un objet par son nom via apr_dso_sym(). Le premier argument est un argument résultat. Le second argument est un handle dso, qu’on a avec apr_dso_open() expliqué précédemment. Le troisième argument est le nom du symbole.

Le code suivant est un extrait de dso-sample.c. Le nom du symbole est « pow » et on récupère un pointeur de fontion en tant qu’objet. Comme on connait l’interface de pow(3), il nous suffit de définir la fonction en tant que type : pow_fn_t.

/* extrait de dso-sample.c, vérif. des erreurs omise */
typedef double (*pow_fn_t)(double x, double y);
pow_fn_t pow_fn;

/* récupérer la fonction pow(3) de libm.so */
apr_dso_sym(
    (apr_dso_handle_sym_t*)&pow_fn,
    dso_h, "pow");

/* appeler pow(3) */
printf("%d ^ %d = %f\n", 2, 2, pow_fn(2, 2));

Si votre programme a des plugins, vous devrez définir des noms symboliques ainsi que leurs interfaces. Par la suite, les développeurs devront s’appuyer sur ces déclarations. Enfin, on appelle apr_dso_unload() pour libérer le module. Cela diminue ainsi la consommation mémoire.

Nouveautés juin

L’avenir des développeurs : oDesk

Cet article vient d’ici : TechCrunch

oDesk, le site qui aitde les clients à trouver et suivre en direct des developpeurs off-shore, a levé 15 millions de dollars dans un tour de table « Series C » dirigé par DAG Ventures. Les investisseurs existants, Benchmark Capital, Globespan Capital Partners, et Sigma Partners ont aussi participé à la levée de fonds. Cela amène les financements de oDesk à une hauteur de 29 millions de dollars.

oDesk donne la possibilité à des compagnies de se ballader au travers de milliers de profiles de développeurs qualifiés, avec une particularité très attrayante : un scoring de capacité qui se base sur des tests du site. Les projets peuvent être complétés en se basant sur un paiement à l’heure ou sur un prix global. Après avoir loué les services d’une équipe, les clients peuvent suivre la progression de leur projet via une timeline visuelle qui envoie des captures d’écrans périodiques des développeurs concernés.

Depuis son lancement le site a été implique dans des mouvements transactionnels de service estimés à 32 millions de dollars (il garde en général 10 %, mais ce n’était pas le cas il y a peu, car la marge était plus grande). Le site a annoncé qu’il allait utiliser ce nouvel apport d’argent frais pour grossir encore plus et « profiter des opportunité inattendue qui se présenteront à l’avenir”.

Incroyable mais vrai

12,000 étudiants de l’école GCSE (une école Anglaise) ont eu un avantage que peu d’autres étudiants peuvent se vanter d’avoir eu : les réponses étaient inscrites sur le dos du questionnaire.

Reuters a expliqué que l’erreur n’a été remarquée qu’après les début de l’examen, mais qu’ils n’allaient pas forcer les étudiants à le repasser parce que moins de 5 % ont remarqué l’incroyable bévue.

Voici comment cela s’explique : “Tous les papiers d’examen  on un copyright qui a un lien avec l’origine du matériel sur le dos de la page… Ce papier en particuler avait beaucoup plus de détail qu’en temps normal pour un papier musical”.

Il y a une une vingtaine de copies qui devraient repasser le test, car, selon les professeurs, les étudiants concernés n’auraient pas été capables de reconnaitre les réponses, si on se base sur les autres tests de ces mêmes personnes.

Dwarf fortress : un jeu pour les geeks.

Ce jeu existe depuis très longtemps, mais pas assez de monde en parle.

Canardpc en a parlé.

Pas mal d’autres personnes en ont parlé un peu partout ailleurs, à vous de voir.
Un bon Wiki en Anglais se trouve ici.

Sa particularité ? Il est laid. Très laid.

Son autre particularité ? Il est puissant. Très très très puissant. C’est impressionnant. Pour résumer, vous dirigez une petite troupe de nains qui doit essayer de survivre. Vous commencez à côté d’une montagne, et vous faites plein de choses : creuser, chasser, faire des réserves, etc. Ensuite vos nains se débrouillent tout seuls. Mais là où ça devient intéréssant c’est toute l’évolution qu’il y a derrière. Tout d’abord, ce monde n’est pas figé et a une histoire. Toute une histoire. C’est un monde entier, dans le sens ou il y a des civilisations qui sont nées, qui ont évolué, qui se sont éteintes, des leader, des monstres qui ont été engendrés et qui ont fait des massacres, des héros qui ont survécu, et chaque personnage a un passé, une vie, et évolue. Et si vous mourrez, vous pourrez redémarrer ailleurs, avec d’autres nains, dans le même monde !

C’est vraiment très très bien, et comme le dit l’auteur : dans ce jeu, si vous perdez, c’est aussi amusant que de gagner, parce qu’il y a plein de choses originales. Je ne parle pas de tout ce qui est évolutions possibles dans le détail, mais voilà un petit résumé : vous pourrez creuser, faire des provisions, faire des champs et les irriguer, faire des ponts, des groupes de pêcheurs ou de chasseurs, des maris et femmes, vous pourrez établir une hiérarchie, arriver à fonder un royaume avec plusieurs centaines de nains qui vont de partout, subir des sorts de la nature (innondations, éboulements, coulées de lave etc.) bon bref tout ce qu’on peut imaginer, et bien plus encore.

Tenez vous bien : l’auteur gagne sa vie grâce aux dons qui lui sont faits ! Pourtant, quand on voit les captures d’écran on se dit « bon sang mais pourquoi des gens paient pour ça ? », je vais vous confier un secret : parce que ce jeu a une profondeur rarement égalée, pour ne pas dire jamais égalée. Simcity et consorts font figure de parents pauvres à côté. Ce type bosse depuis plusieurs années dessus et continue à le faire évoluer pratiquement tous les jours : son blog est ici.

A vous de voir, vous pouvez le télécharger ici.

Statistiques : de la pub de manière incroyable

C’est absolument impossible que quelqu’un soit tombé sur ma page en tapant l’un de ces termes :

  • (microsoft) and (idees or ideas or start-up)
  • (microsoft or windows or msn) and drm
  • bessemer venture partner shasta ventures catamount ventures

Voici, à mon avis, l’explication : plusieurs mecs ont fait des « faux » aspirateurs de site qui mettent un referer qui fait croire que leur origine vient d’un résultat d’une recherche sur google. Ainsi ils font passer leur pub sur les statistiques Internet. Aussi ingénieux que geek, non ?

Top 16 sur un total de 16 groupes de mots-clés
# Hits Mots-clés
1 4 15.38% faire le gros malin
2 4 15.38% olivier pons
3 2 7.69% %i64d unix
4 2 7.69% (microsoft) and (idees or ideas or start-up)
5 2 7.69% blog olivier pons immobilier
6 2 7.69% http://.olivier.pons.free.fr
7 1 3.85% (microsoft or windows or msn) and drm
8 1 3.85% bessemer venture partner shasta ventures catamount ventures
9 1 3.85% http://olivier.pons.free.fr/blog/geek/
10 1 3.85% php 5 tutorial
11 1 3.85% pons
12 1 3.85% pons olivier myspace
13 1 3.85% produit démonstrateur
14 1 3.85% site:.olivier.pons.free.fr
15 1 3.85% utimaco or bitlocker or ((efs or rms or drm or gestion de droit
16 1 3.85% zeemoz

Librairie Apr : tutoriels 10 et 11

10. Options de la ligne de commande

Pour les outils en ligne de commande (CLI, Command Line Interface), les options qu’on donne en ligne de commandes sont souvent utilisées. La librairie libapr met des fonctions à disposition qui facilitent grandement la gestion des options fournies en ligne de commande. Voici un extrat de getopt-sample.c.

/* extrait de getopt-sample.c */
static const apr_getopt_option_t opt_option[] = {
    /* énumération comme suit :
     * {opt. longue}, {opt. courte},
     * {flag "argument qui suit"}, {description} :
     */

    /* -i nomfichier or --in nomfichier : */
    { "in", 'i', TRUE, "fichier entrant" },

    /* -o nomfichier or --out nomfichier : */
    { "out", 'o', TRUE, "fichier sortant" },

    /* -h or --help : */
    { "help", 'h', FALSE, "voir l'aide" },

    /* sentinelle de fin : */
    { NULL, 0, 0, NULL },
};

En premier lieu, il faut fournir un tableau d’éléments apr_getopt_option_t. On l’appelle (ici) option-list. Chaque élément a quatre variables :

  1. une option longue ;
  2. une option courte ;
  3. un flag « argument qui suit », pour préciser si cette option nécessite un argument qui doit la suivre ;
  4. une description.

Par exemple, pour l’option « help » :

  • Une option longue : ‘–help’ :
  • Une option courte : ‘-h’.

Les options courtes sont obligatoires et les options longues sont optionnelles. On peut tout à fait mettre NULL pour une option longue. La troisième variable précise si un argument supplémentaire doit suivre cette option. Par exemple si une option de ligne de commande fonctionne ainsi  ‘–in nomfichier’, c’est à dire qu’il faut obligatoirement préciser un nom de fichier, il faut mettre ce flag à vrai (TRUE). Ainsi, si le programme est exécuté et qu’on donne cette option sans donner un argument, par exemple ‘./a.out -in’, une erreur est levée.
Enfin, le tableau de la liste des options doit se terminer par une sentinelle vide qui précise que la liste est finie (voir l’exemple précédent).
Pour parcourir les options fournies dans la ligne de commande, if faut tout d’abord initialiser le parser en appelant ‘apr_getopt_init()’ (pour initialiser un objet apr_getopt_t) puis faire une boucle en s’aidant du tableau des options. Ensuite, on appelle en boucle apr_getopt_long() tant qu’il renvoie APR_SUCCESS. Voici un extrait de getopt-sample.c :

/* extrait de getopt-sample.c */
/* initialiser apr_getopt_t */
apr_getopt_t *opt;
apr_getopt_init(&opt, mp, argc, argv);
/* parcourir toutes les options via opt_option[] */
while ((rv = apr_getopt_long(opt,opt_option,
                             &optch,
                             &optarg)) == APR_SUCCESS) {
...etc.

Dans la boucle, apr_getopt_long() enumère les options passées en ligne de commande une par une. Si l’option trouvée fait partie de la liste des options, apr_getopt_long() renvoie APR_SUCCESS et initialise la valeur de optch en conséquence. Si l’option a un argument supplémentaire apr_getopt_long() le lit et initialise la valeur de optarg.

Voyons un exemple concret. Imaginons que vous lanciez le programme en y ajoutant une option et une valeur associée : ‘./getopt-sample -h -i foo.txt’. Lors de la première boucle, apr_getopt_long() trouve ‘h’ dans la liste des option. Donc, apr_getopt_long() renvoie APR_SUCCESS et initialise optch avec la valeur ‘h’. Sur la boucle suivante, apr_getopt_long() trouve ‘i’ dans la liste des options, et comme ‘i’ nécessite un argument qui doit le suivre, il y a lecture de l’argument suivant, ‘foo.txt’. Ainsi, apr_getopt_long() renvoie APR_SUCCESS, avec optch qui vaut ‘i’ et optarg qui vaut « foo.txt ». Lors de la boucle suivante, apr_getopt_long() ne trouve plus d’options et renvoie par conséquent APR_EOF.

11. memory map (mmap)

mmap signifie « mapping mémoire ». Ce qui veut dire « mapper » des fichiers en mémoire. mmap est principalement utilisé pour :

  • Lire/écrire dans des fichiers le plus rapidement possible ;
  • Allouer un espace mémoire consécutif plus gros (gestion spécifique à chaque système d’exploitation) ;
  • Partage mémoire entre différents processus.

Pensez au cas où vous voulez lire un fichier en entier en une fois. Dans ce cas il faut faire un buffer, lire du début jusqu’à la fin dans une boucle. Le code ressemblerait à cela :

/* code simpliste pour lire le contenu d'un fichier */
apr_file_t *fp;
apr_file_open(&fp, filename, APR_READ, APR_OS_DEFAULT, mp);
while (1) {
    char buf[1024];
    apr_size_t len = sizeof(buf);
    rv = apr_file_read(fp, buf, &len);
    if (rv != APR_SUCCESS) {
        break;
    }
    /* scan buf */
}
apr_file_close(fp);

On peut faire mieux, avec apr_mmap_t :

/* extrait de mmap-sample.c, vérif. des erreurs omise */
apr_file_open(&fp, filename, APR_READ, APR_OS_DEFAULT, mp);
apr_finfo_t finfo;
apr_file_info_get(&finfo, APR_FINFO_SIZE, fp);
apr_mmap_t *mmap;
apr_mmap_create(&mmap, fp, 0, finfo.size, APR_MMAP_READ, mp);
/* scan mmap->mm */
apr_mmap_delete(mmap);

Si le fichier est suffisamment gros, le code basé sur mmap sera plus rapide.
Plus important encore, mmap aide à éviter la fragmentation mémoire. La plupart des systèmes (qui doivent gérer les allocations mémoire) se trouvent confronté au problème de fragmentation mémoire, mais mmap n’entre pas dans le cadre d’allocation mémoire dans l’espace utilisateur. Malheureusement, sur certains systèmes, mmap est parfois lent et bogué.

On peut utiliser mmap pour modifier des fichiers. On ouvre le fichier avec APR_WRITE, puis on « mmap » le fichier en précisant le flag APR_MMAP_WRITE.

REMARQUE : Il est interdit de « mmap-er » un fichier ouvert avec le flag APR_BUFFERED. Le code suivant renverra toujours l’erreur APR_EBADF :

/* Exemple mmap BOGUE */
apr_file_t *fp;
apr_mmap_t *mm;
apr_file_open(&fp,
    fname,
    APR_READ|APR_BUFFERED,
    APR_OS_DEFAULT, mp);
rv = apr_mmap_create(&mm,
    fp, 0,
    finfo.size,
    APR_MMAP_READ, mp);
/* BOGUE : le résultat sera TOUJOURS :
 * rv==APR_EBADF
 */

Les vacances…

De retour de vacances, tout s’est très bien passé.

  1. Jeudi 12 juinLe matin, présentation au boulot

    Ensuite course pour prendre le train.

    Arrivée à 20h30 à Angers.

  2. Vendredi 13 juinLa petite avait de la fièvre. Elle est montée à 40,1 dans la nuit du 13 au 14.

    Elle a quand même découvert le centre ville, avec un grand parc sympa en trois parties, pour tous les âges.

  3. Samedi 14 juinLa fièvre de la petite est partie le matin même. Elle pouvait provenir de plein de choses : grosse dent qui pousse, poussée de croissance, etc.

    C’était le grand jour pour Karine : sa soirée, préparée depuis un an, avec 65 personnes.

    Tout s’est très bien déroulé, ça a peut-être été un peu moins festif que prévu et les personnes sont parties assez tôt. Enfin, « assez » = 2-3 heures du matin.

  4. Dimanche 15 juinDécouverte d’un endroit fabuleux, magique, génial… que pour Inès : le jardin aux plantes. A Angers et comme dans toutes les villes un peu vertes, je pense qu’il est plus facile d’entretenir de grandes surfaces boisées et c’est peut-être pour ça qu’il y a beaucoup de parcs verts et très bien entretenus. Il est vrai que si on essayait de faire ce genre de chose sur Marseille ça ne tiendrait pas longtemps.
  5. Lundi 16 juinDépart pour Cancale. 2h30 de route. Arrivée à minuit.
  6. Mardi 17 juinJournée géniale à la plage, plein de photos aussi belles que rigolotes.
  7. Mercredi 18 juinApparemment on a eu de la chance parce qu’il n’a toujours pas plu (enfin une toute petite bruine le matin, négligeable).
  8. Jeudi 19 juinLe matin une ballade du haut de Cancale, avec une très belle vue.

    Arrêt au magasin de souvenirs. Comme d’habitude on a acheté des choses qui ne serviront pas, c’est la vie !

    Retour sur Angers, arrivée en début d’après midi.

  9. Vendredi 20 juinJournée extraordinaire pour les grands : journée à la vallée des singes. Je dis pour les grands, parce qu’à deux ans, les petits, regarder des singes pendant plusieurs heures, ce n’est pas leur tasse de thé.
  10. Samedi 21 juinMatin : marché puis jardin des plantes.

    Après midi : découverte d’un endroit super sympa : le lac du Maine.

    Coucher très tard (1h30) après avoir vu « la môme ».

  11. Dimanche 22 juinLever très tôt. Arrivée à 13h30. Chaleur étouffante comparé à Angers ! Mais au moins il n’y a pas un seul nuage dans le ciel. Grande consolation

Flex et JSON

Cette petite astuce va peut-être vous faire gagner du temps si vous débutez et vous voulez écrire rapidement quelque chose :
Cet article écrit ici est très pratique et explique très rapidement comment utiliser JSON et Flex.
Malheureusement c’est il n’explique pas clairement une chose :
Il faut installer la corelib de Adobe pour avoir JSON.
Voici comment faire : téléchargez la corelib d’Adobe ici.
Puis vous le décompressez dans le répertoire que vous voulez. Moi j’ai choisi le plus près d’Adobe, donc dans le répertoire des programmes, section Adobe :

C:\Program Files\Adobe\Flex3.0 - corelib\bin

J’ai crée un répertoire au nom explicite :

Flex3.0 - corelib

Donc j’ai décompressé la totale ici :

C:\Program Files\Adobe\Flex3.0 - corelib

Ensuite, sous Flex, vous créez un nouveau projet, vous faites tout le code que vous voulez, mais il ne faut surtout pas oublier d’y adjoindre le core dès que vous voulez du JSON. Il suffit de cliquer avec le bouton droit de la souris sur le nom du projet, de choisir propriétés (properties), et là une fenêtre s’ouvre, choisissez Flex Build Path et une fenêtre à côté avec deux onglets va s’afficher : choisissez Library Path, et là choisissez le bouton Add SWC (Ajout un fichier SWC) et allez cherche ce fichier binaire :

C:\Program Files\Adobe\Flex3.0 - corelib\bin\corelib.swc

Et voilà !
Dans votre source il ne vous reste plus qu’à faire l’import :

import com.adobe.serialization.json.JSON;

Puis de vous en servir. Voilà un exemple :

  1. Déclaration de la fonction appelée lorsque le chargement est terminé :
      private function aggravationsJSON(event:ResultEvent):void {
       var rawData:String = String(event.result);
       var test:String = JSON.decode(rawData);
       var aggravations:Array = JSON.decode(rawData) as Array;
       // puis plein de code à vous de développer !
      }
    
  2. Enfin la déclaration d’un service avec deux paramètres :
    1. part, valeur = 578 ;
    2. tagg, valeur = 1.
     <mx:HTTPService id="sportsRequest" url="../aggravations.php"
      useProxy="false" method="GET" resultFormat="text"
      result="aggravationsJSON(event)">
      <mx:request xmlns="">
       <part>578</part>
       <tagg>1</tagg>
      </mx:request>
     </mx:HTTPService>

En espérant qu’avec ce morceau de code et l’aide, vous puissiez avancer un peu plus vite !