[Scheme] で Web アプリかもしれない
MP3 を管理しようと思い立ったので、まずid3libなるものの Gauche バインディングを作ることを試みようと思います。id3lib は ID3 タグを扱う C++ ライブラリです。使ったこと無いですが。この企画がいつまで続くかも分からないですが。
さて、 Gauche 本体についてくる C++ バインディングのサンプルとして名高い mqueue-cpp の README をお手本に、とにかくやってみることにします。
まずスケルトンを生成するみたいです。多分第二引数がディレクトリ名で、第三引数がモジュール名でしょう。適当につけます。
gauche-package generate id3lib media.id3lib
今回は C++ のライブラリを使うので、コンパイラを特別に指定する必要があるそうです。
C のライブラリであれば、Gauche がコンパイルされたコンパイラを使えば良い(guache-config が知っている)ので、特に設定は要らないっぽい。
=== Makefile.in ================================================================== --- Makefile.in (revision 1210) +++ Makefile.in (revision 1211) @@ -24,6 +24,8 @@ OBJEXT = @OBJEXT@ EXEEXT = @EXEEXT@ +CXX = @CXX@ + # Module-specific stuff PACKAGE = id3lib @@ -45,7 +47,7 @@ all : $(TARGET) id3lib.$(SOEXT): $(id3lib_SRCS) - $(GAUCHE_PACKAGE) compile --verbose id3lib $(id3lib_SRCS) + $(GAUCHE_PACKAGE) compile cc=$(CXX) --verbose id3lib $(id3lib_SRCS) check : all @rm -f test.log
次に、id3lib_glue.h を作ります。glue は、グルー言語のグルーだと思います。多分つなぎとかそういう意味でしょう。あとで調べるかもしれない。
mqueue_glue.h を参考に、型名等を合わせてそれっぽく書いてみます。
#include <id3/tag.h> #include <gauche.h> #include <gauche/extend.h> SCM_DECL_BEGIN // start "C" linkage extern ScmClass *ID3TagClass; #define ID3LIB_P(obj) SCM_XTYPEP(obj, ID3TagClass) #define ID3LIB_UNBOX(obj) SCM_FOREIGN_POINTER_REF(ID3_Tag*, obj) #define ID3LIB_BOX(ptr) Scm_MakeForeignPointer(ID3TagClass, ptr) extern void Scm_Init_ID3Tag(); SCM_DECL_END
つぎに id3lib_glue.cpp も、同じようにそれっぽく書いてみます。
#include "id3lib_glue.h" ScmClass *ID3TagClass; static void id3tag_print(ScmObj obj, ScmPort *out, ScmWriteContext *ctx) { ID3_Tag *tag = ID3LIB_UNBOX(obj); /* とりあえずポインタの値を出力しとく */ Scm_Printf(out, "#<id3tag \"%p\">", tag); } static void id3tag_cleanup(ScmObj obj) { ID3_Tag *q; q = ID3LIB_UNBOX(obj); delete q; } extern void Scm_Init_id3lib_lib(ScmModule*); void Scm_Init_ID3Tag() { ScmModule *mod; /* Register this DSO to Gauche */ SCM_INIT_EXTENSION(id3lib); /* Create media.id3lib module */ mod = SCM_MODULE(SCM_FIND_MODULE("media.id3lib", TRUE)); ID3TagClass = Scm_MakeForeignPointerClass(mod, "<id3tag>", id3tag_print, id3tag_cleanup, SCM_FOREIGN_POINTER_KEEP_IDENTITY|SCM_FOREIGN_POINTER_MAP_NULL); /* Initialize stub functions */ Scm_Init_id3lib_lib(mod); }
mqueue-cpp の README には、Scm_MakeForeignPointerClass のところを、特に cleanup 手続きについて注意するように書いてあります。GC 関係だと思われますが、とりあえずそんなに気にしないでおくことにします。中のオブジェクトが Scheme 世界と交わらなければ大丈夫なはず。
この部分が非常に謎。
/* Register this DSO to Gauche */
SCM_INIT_EXTENSION(id3lib);
stub ファイルがこんな感じ。
;;; ;;; id3liblib.stub ;;; " #include \"id3lib_glue.h\" " (define-type <id3tag> "ID3_Tag*" "ID3Tag" "ID3LIB_P" "ID3LIB_UNBOX" "ID3LIB_BOX") (define-cproc make-id3tag (name::<const-cstring>) (expr <id3tag> "new ID3_Tag(name)")) (define-cproc id3tag-filename (tag::<id3tag>) (expr <const-cstring> "tag->GetFlieName()")) ;; Local variables: ;; mode: scheme ;; end: