octobre
2010
Diverses fonctions
Je vais présenter ici quelques fonctions utiles. Pour des questions de faciliter, j’ai créé deux nouvelles méthodes pour le module TagLib bien qu’elles n’aient rien avoir avec taglib.
Utiliser un bloc
La méthode TagLib.block ne prend aucun paramètre, mais un bloc doit lui être fourni. Elle exécute ce bloc en lui passant comme argument l’objet TagLib et retourne le bloc sous la forme d’un Proc.
$ irb
> require './lib/taglib2.rb'
=> true
TagLib.block{|a| p a}
TagLib
=> #<Proc:0xb75ba510@(irb):2>
Voici la fonction implémentant ce comportement.
block(VALUE self)
{
rb_yield(self);
return rb_block_proc();
}
rb_yield permet d’appeler le bloc passé à la méthode alors que rb_block_proc permet de le manipuler sous la forme d’un Proc.
Utiliser des paramètres optionnels
Je propose d’écrire l’équivalent de code écrit en ruby.
tab.to_a
tab.each{|s| $stdout.puts s}
tab[0]
end
Le dernier argument lors de la déclaration de la méthode TagLib.n vaut -1 ce qui indique que la méthode ne possède pas un nombre d’arguments fixees. La fonction rb_scan_args permet de récupérer de manière propre les paramètres passés à la méthode. Le troisième argument de cette fonction est une chaîne de caractère représentant deux chiffres. Le premier indique le nombre de paramètres obligatoires, le second indique le nombre de paramètres optionnels.
n1(VALUE str)
{
return rb_funcall(rb_stdout, rb_intern("puts"), 1, str);
}
VALUE
n(int argc, VALUE* argv, VALUE self)
{
VALUE tab;
rb_scan_args(argc, argv, "01", &tab);
if (NIL_P(tab))
tab=rb_ary_new3(2, rb_str_new2("Salut"), rb_str_new2("Re"));
rb_funcall(tab, rb_intern("to_a"), 0);
rb_iterate(rb_each, tab, n1, Qnil);
return RARRAY(tab)->ptr[0];
}
TagLib.n peut donc être appelée avec un paramètre ou sans. Si aucun argument n’a été passé (tab=nil), tab est initialisé en créant un tableau contenant deux objets String. On vérifie ensuite que tab appartient à la classe Array ou s’en rapproche (duck typing). rb_funcall permet d’appeler une méthode (deuxième argument) d’un objet (premier argument) avec un certain nombre (troisième argument) de paramètres (arguments suivant). rb_intern permet d’obtenir la méthode à partir d’une chaîne de caractères.
La fonction n1 est ensuite appelé pour chacun des éléments du tableau grâce à rb_iterate. LA méthode retourne, finalement, le premier élément de tab, la macro RARRAY permettant d’accéder à la structure interne d’un objet de la classe Array, le champ ptr permettant d’accéder aux éléments.
Salut
Re
=> "Salut"
> TagLib.n(["Bonjour"])
Bonjour
=> "Bonjour"
Liens utiles
Quelques liens qui m’ont aidé à écrire des extensions pour ruby en C :
le fichier README.EXt fourni avec ruby,
ruby-doc.
En ce qui concerne taglib :
l’exemple dans les sources de taglib,
le fichier bindings/c/tag_c.h.
Sources
Le code, présenté dans ces billets, implémentant le module, TagLib est téléchargeable ici.
Conclusion
Cette série d’articles est finie. J’espère qu’ils vous seront utiles.