dimanche 29 janvier 2012

L'oeil extérieur

Depuis que quelques bonnes âmes essayent Médoc, je retrouve nombre de petites limitations, ou de cas particuliers que j'avais ignoré un peu rapidement. Le résultat, c'est que le logiciel s'améliore lentement, mais sûrement.

Ce sont des choses bêtes: la localisation, par exemple, qui envoyait des dates en français à la base de données. Ou le support multi-devices: Sane ne reconnait que mon scanner HP, j'ai donc paresseusement simplifié Médoc en prenant le premier device disponible. Mais une simple webcam, par exemple, est considéré comme étant un device supplémentaire, et tout d'un coup, l'hypothèse ne tient plus.

La morale de cette histoire, c'est:
- Eat your own dog food
- Mais faites tester par d'autres!

dimanche 22 janvier 2012

Un client Twitter en OCaml

Pourquoi s'arrêter en si bon chemin? Voici un nouvel œuf de canard: le même client Twitter pour l'API stream, mais cette fois-ci en OCaml. Utilisant Yojson et OCurl, c'est le port copie conforme du client C++.

Si jamais je me décidais à enregistrer les messages dans une base de données, c'est plutôt à partir du client OCaml que je continuerais.

mardi 17 janvier 2012

Oeuf de canard - C++ et zlib

Un vieil œuf de canard que je viens de poster: mon vieux wrapper zlib est maintenant dans le nid douillet de Github, avec deux binaires triviaux pour la compression et la décompression.

vendredi 13 janvier 2012

Peaufinage

Quelques améliorations de Médoc: tout d'abord, je rends l'OCR optionnel, puisque la version 2 de Tesseract, empaquetée sous Debian, est assez buggée et crashe régulièrement. Si un document ne passe pas, allez donc désactiver l'option.

Ensuite, j'ai tenté d'améliorer le look de la boite de dialogue du scan: la bibliothèque Sane contient déjà la notion de groupe, il suffisait donc de recoller les morceaux. Une boite de dialogue typique ressemble à ça:

Notez également que la barre de progression est maintenant intégrée, ce qui l'évite de surgir sur le bureau alors que l'on est en train de faire autre chose pendant un long scan.

Un gros morceau sera de revoir en détail l'ordre des contrôles dans chaque boite de dialogue, afin de simplifier la navigation par la touche Tab.

dimanche 8 janvier 2012

Streaming API Twitter

Non, je ne me suis pas encore vendu aux médias sociaux, mais puisque je pourrais en avoir besoin bientôt, je me suis lancé dans l'écriture d'un tout petit programme en C++ destiné à lire les feeds Twitter en temps réel. Combinant curl et json_spirit, suffisamment grand pour ne pas être pratique à poster, mais suffisamment petit pour ne pas valoir un projet à lui tout seul, c'était le candidat parfait pour mon dépôt "Œufs de canard" dont je parlais dans un post précédent (j'avais en effet déjà une idée derrière le bec).

Le code se trouve ici. L'on lancera le programme ainsi:

./twitterstream -u username -p password -k mot1 -k mot2 -k mot3...

Et devraient surgir à l'écran les messages filtrant sur un des mots-clé passés dans les options -k.

Je suis impressionné par le débit: sur des mots relativement courants, ça descend à toute vitesse.

Je me tâte maintenant à ajouter une couche de persistance vers une base de données... Peut-être après Médoc v2!

Oeufs de canard

J'inaugure mon nouveau dépôt Œufs de canard, où je placerai mes programmes de test, ce qui sera plus simple que de faire d'interminables listings plus ou moins bien formatés ici. Plus de contenu, moins de blabla, voici mes vœux pour ce blog en 2012 (vous allez me dire, ça commence bien...).

samedi 7 janvier 2012

J'oubliais...

Et bonne année, aussi!

vendredi 6 janvier 2012

Covariance

C'est étrangement une fonctionnalité qui semble relativement peu connue des programmeurs C++: la covariance des types de retours dans les fonctions surchargées.

L'exemple standard est la déclaration d'une méthode "clone", qui renvoie une copie de l'objet. Prenons une classe A:


class A
{
public:
virtual ~A();
virtual A * clone() const;
};

Maintenant, comment écrire une classe B dérivant de A, de manière à ce que la méthode clone fonctionne, c'est à dire renvoie une instance de B si le type sous-jacent est B? Ou plus exactement, quel devrait être le type de retour de la méthode clone de B?

L'on peut bien entendu retourner A. C'est clair, net et précis lorsque l'on travaille avec A, mais c'est dommage lorsque l'on travaille directement avec B: appeler clone renvoie un pointeur sur A, alors que l'on sait pertinemment que c'est un B, et on doit donc le caster vers B pour travailler avec.

Profitons donc de cette fonctionnalité introduite dans C++98, qui dit que si une méthode virtuelle renvoie un pointeur, l'on peut surcharger cette méthode avec un type de retour pointeur vers un objet dérivé. L'on écrira donc:

class B : public A
{
public:
B * clone() const;
};

Et la méthode clone fonctionnera exactement de la manière désirée.

Il est à noter que le type de retour peut-être différent du type parent: si A dérive de B, et C dérive de D, une méthode de A retournant C peut être surchargée dans B comme retournant D.

Il est à noter également que malheureusement, cette fonctionnalité devient de moins en moins utile: de nos jours, il est de plus en plus rare de renvoyer un pointeur à poil, et il n'est pas possible d'obtenir le même résultat avec un shared_ptr, par exemple. Dans ce cas, il faudra renvoyer systématiquement le type parent, et faire un cast.