先日のエントリからの調べ物として、まずgjsでgobject-introspectionを使用する方法を残しておく。gjsはgobject-introspectionで実現していて、gobject-introspectionはそれ自身がgobject-introspectionをサポートしているので、gjsを使えば簡単なメタプログラミングが実現できるというわけだ。
ローカルでgobject-introspectionをサポートするAPIにどのようなものがあるかは、インストール先のgir-1.0フォルダを探して見てみると良い。典型的なLinux distroの場合は /usr/share/gir-1.0 などにあるだろう。
gjsのgirバインディングは素直だ。使いたいモジュールは imports.gi.XXX でアクセスできる。
var GIR = imports.gi.GIRepository;
GIRネームスペースには、(ドキュメントを読んでもらえればわかるが)GIRepositoryというクラスが存在する。gjsからアクセスする場合は、共通の型名プレフィックスである GI を除いた Repository がクラス名となる(共通のプレフィックスが何になるかは、*.girファイルに記述してあるので、gjsは機械的に名前を計算できる)。
girベースのAPIには、classが定義されており、その中にはinstanceメンバーとstaticメンバーが存在する。instanceメンバーの場合、*.girファイルには関数の定義部分に instance-parameter というXML elementが存在している。それ以外はstaticメンバーとなる。
staticメンバーにアクセスする場合は、クラスをあらわすオブジェクトのメンバーとして呼びだせば良い。Repositoryには、 girepositoryget_default() という、デフォルトのRepositoryを返す関数がある。girのclassにはsymbol-prefixというものが定義されており、これは関数名の解決で使用される。同様に、GIRのネームスペースには、ネームスペースのプレフィックスも規定されている。GIRepositoryネームスペースのプレフィックスは "g" で、Repositoryクラスのプレフィックスは "irepository" だ。
ここから、girepositorygetdefault()という関数は、GIRepositoryネームスペースのRepositoryクラスのgetdefault()というメソッドとして、定義されることになる。たとえば、get_default()の呼び出しはこうなる:
var GIR = imports.gi.GIRepository; var repo = GIR.Repository.get_default();
これでrepo変数にRepository型のオブジェクトが格納されたことになる。
gjs> repo [object instance proxy GIName:GIRepository.Repository jsobj@0x7f8cbe1357f0 native@0x21d6420]
インスタンスメソッドのマッピングも簡単だ。名前の解決はstatic関数と同様に行われる。引数については、前述の通り、インスタンスメソッドの定義には instance-parameter というXML elementが含まれている。この引数は、gjsのAPIではthisの扱いになり、引数とはならない。
girepositorygetloadednamespaces()関数を呼び出してみよう。この関数もRepositoryクラス内で定義されている。唯一のパラメーターが instance-parameter なので、gjsでインスタンスメソッドとなった時には、引数は存在しない。
gjs> repo.get_loaded_namespaces() GLib,GObject,GIRepository
girepositorygetninfos() は、2つ引数をとり、最初はインスタンス パラメーターであり、最後はネームスペース名となる。戻り値には、そのネームスペースに含まれる「定義」の数を返す。
gjs> repo.get_n_infos("GIRepository"); 152
それぞれの要素は girepositoryget_info() で取得できる。
gjs> var info = repo.get_info("GIRepository",0); gjs> info [boxed instance proxy GIName:GIRepository.BaseInfo jsobj@0x7f05f0735a60 native@0x715320]
gjsを使ったGIRepositoryの基本的な操作は、概ねこの辺りが分かれば出来そうだ。