David Madore's WebLog: Perdu dans un labyrinthe de petites API toutes semblables

Index of all entries / Index de toutes les entréesXML (RSS 1.0) • Recent comments / Commentaires récents

↓Entry #1999 [older| permalink|newer] / ↓Entrée #1999 [précédente| permalien|suivante] ↓

(dimanche)

Perdu dans un labyrinthe de petites API toutes semblables

J'ai écrit une page web qui fait des calculs en JavaScript (il s'agit toujours d'animations de E8 mais peu importe), calculs que je voudrais faire exécuter hors du cadre d'un navigateur (en l'occurrence pour faire une nouvelle vidéo à mettre sur YouTube), si possible sans réécrire complètement le code en autre chose que JavaScript[#]. Bref, exporter les résultats de ces calculs, les sauvegarder dans un fichier (sous un format à peu près quelconque, typiquement un dump texte des résultats, que je saurai ensuite convertir assez facilement).

Je cherche donc la chose suivante : un environnement JavaScript « standalone », c'est-à-dire hors d'un navigateur (mais à la limite ce n'est pas bien grave si je dois lancer un navigateur) avec une simple fonction pour écrire un fichier (dans lequel je pourrai sauvegarder le résultat de mes calculs ; enfin, il me faudra ouvrir plusieurs fichiers différents parce que les résultats sont un peu longs, je voudrais faire un fichier par image d'une animation).

Pour résumer, je veux juste écrire du texte dans un fichier depuis JavaScript. Ça n'a pas l'air de demander beaucoup, n'est-ce pas ? C'est pourtant la porte d'entrée d'un labyrinthe cauchemardesque de presque-solutions toutes aussi décevantes les unes que les autres. Faisons un peu le tour.

  • Firefox fournit une version standalone de son moteur JavaScript SpiderMonkey, et une autre de son moteur Rhino (et tous deux sont packagés par Debian), sous les noms smjs et rhino respectivement. Mais aucune API ne semble disponible pour ouvrir un fichier (il y a eu un truc dans ce sens, mais il fallait l'activer spécialement et de toute façon il est marqué comme obsolète sans aucune indication de ce qui le remplace, merci bien).
  • Il y avait un projet appelé JSlibs, qui semblait faire exactement ce que je voulais (=fournir une interface JavaScript pour un certain nombre de bibliothèques usuelles), mais ce projet a l'air mort et a probablement bitroté. Inutile donc d'essayer de comprendre comment on est censé l'installer.
  • Il y a un projet appelé CommonJS qui prétend définir un standard sur la manière d'appeler différentes bibliothèques depuis JavaScript, et qui a certainement ce que je veux. Mais bon, c'est un standard, pas une implémentation, donc ça ne m'aide pas tant que ça. Il prétend avoir un grand nombre d'implémentations, mais quand je regarde la plupart d'entre elles, soit je ne comprends rien, soit le projet est mort, soit il a l'air abominable à installer, soit la partie implémentée est juste un module particulier et pas celui qui permet d'ouvrir un fichier, bref, je ne vois rien qui me convienne. Sauf peut-être :
  • Node.js, dont j'entends énormément parler, est un cadre général pour écrire des serveurs Web en JavaScript : ils ont forcément de quoi ouvrir un bête fichier et écrire du texte dedans. Mais d'après ce que je comprends çà et là, Node.js utilise un mécanisme d'entrées-sorties asynchrones, basées sur des événements, quelque chose de probablement approprié pour écrire un serveur Web, mais complètement inadapté pour simplement écrire du texte dans un fichier. Si je mets le doigt dedans, je vais sans doute souffrir.
  • On me souffle qu'il est possible d'utiliser le moteur JavaScript V8 de Google depuis du code C++, et certainement de donner au code JavaScript de quoi communiquer avec le C++ pour y faire ce que je veux. Bon, mais C++ est le langage de programmation dont je ne connais rien du tout et dont je ne veux surtout rien connaître. Dommage.
  • On me souffle aussi que mon problème serait très simple sous Windows. Bon, mais je n'ai pas accès à un Windows (sauf un vieux XP dans une machine virtuelle, je doute que ça convienne vraiment).
  • Sinon, le projet Gnome est réputé exporter toutes ses API (dont certainement ce qu'il faut pour écrire un fichier…) sous une forme telle qu'elles soient utilisables dans un grand nombre de langages de programmation. Il y a même un cadre général pour faire ça de façon automatisée : GObjectIntrospection. Et il y a non pas un mais deux interpréteurs JavaScript (subtilement différents et confusants) qui font plus ou moins partie du projet Gnome : l'un s'appelle gjs, l'autre s'appelle Seed. C'est très certainement ce que je veux : pour programmer des petites choses simples en JavaScript qui interagissent avec mon environnement graphique ou mon système d'exploitation, des bindings Gnome semblent idoines. Le problème est l'absence complète de documentation de l'utilisation des API dans le cadre de ces deux projets : je trouve vaguement un exemple utilisant gjs (pour ouvrir une fenêtre), je trouve cette page de doc dont je ne sais même pas d'où elle sort, mais inexplicablement il n'y a aucune méthode contenant le mot file (et si j'essaie d'utiliser GLib.io_channel_new_file() comme il semble logique d'après l'API C, ça n'existe pas), les exemples Seed que je trouve ici semblent avoir essentiellement disparu, les traces que j'en retrouve néanmoins par exemple là ne marchent pas.

Bon, après des heures et des heures à naviguer à tâtons dans ce labyrinthe, je crois avoir trouvé que ceci fonctionne avec Seed, pour écrire foobar dans le fichier monfichier, mais je ne comprends vraiment pas d'où vient cette API ni comment j'étais censé la deviner : var Gio = imports.gi.Gio; var file = Gio.file_new_for_path("monfichier"); var fstream = file.replace(); var dstream = new Gio.DataOutputStream.c_new(fstream); dstream.put_string("foobar"); fstream.close(); ; l'ennui c'est que je ne comprends rien à ce que je fais, je ne sais pas pourquoi ça ne marche que sous Seed et pas sous gjs alors qu'ils sont censés utiliser la même API, je ne sais pas ce que c'est que Gio et pourquoi il faut chercher imports.gi.Gio alors que cette page précédemment citée évoque imports.gi.GLib, bref, je ne comprends rien à ce que je fais. Qu'est-ce que c'est que cette fonction Gio.file_new_for_path et quel est son rapport avec ce qui est ici, ou ce qui est là ? Je suis vraiment perdu dans un labyrinthe.

[Ajout : Sous gjs, apparemment, il faut faire : var Gio = imports.gi.Gio; var file = Gio.file_new_for_path("monfichier"); var fstream = file.replace(null, false, 0, null); var dstream = new Gio.DataOutputStream.new(fstream); dstream.put_string("foobar", null); fstream.close(null); ; par ailleurs, la raison de ma confusion sur les API est qu'il existe à la fois une API IOChannel dans la GLib et aussi une API GIO, qui n'a rien à voir sauf qu'elle fait à peu près les mêmes choses de façon gratuitement et stupidement différentes, juste pour emmerder le programmeur. Et apparemment on ne peut pas utiliser les fonctions de manipulation de fichiers de la GLib depuis gjs/Seed, ou en tout cas je n'ai pas réussi, par exemple GLib.open() n'existe pas alors que logiquement il devrait. Tout ceci est incompréhensible.]

C'est un peu le problème des projets en logiciel libre où tout ce qui se fait un jour est rendu obsolète le jour suivant parce qu'ils ont décidé que ce n'était plus la bonne façon de faire, donc toutes les docs qu'on trouve sont obsolètes et on ne sait jamais ce qui a remplacé quoi. Quel chaos !

[#] Pas que JavaScript soit le langage le plus adapté du monde pour ce que j'ai à faire — loin de là — mais maintenant que le code est écrit, je n'ai pas envie de le réécrire complètement en Perl/Python/quidlibet.

↑Entry #1999 [older| permalink|newer] / ↑Entrée #1999 [précédente| permalien|suivante] ↑

Recent entries / Entrées récentesIndex of all entries / Index de toutes les entrées