[groonga-dev,02062] Haskell版C APIバインディングを作成しました その2

Back to archive index

hiroshi hatake cosmo****@gmail*****
2014年 1月 17日 (金) 06:42:38 JST


畑ケです。
>> > "Groonga"への表記統一の作業をしているうちに
>> > Groongaのバインディングを作ってみたら面白そうだと思い立ちました。
> ありがとうございます!とても助かっています!
おぉ、そう言って頂けるとありがたいです。そろそろ残り箇所が少なくなってき
たかなと思います。(が、そうでもないんでしょうか…。)
>> > Groonga 3.1.1のgroonga.hからc2hsc (
>> > http://hackage.haskell.org/package/c2hsc )を用いて静的に解析を行い、
>> > hsc2hs (
>> > http://www.haskell.org/ghc/docs/latest/html/users_guide/hsc2hs.html ) を
>> > 用いてhsc2hs向けマクロを一斉に展開するという方針で作成しました。
>> > (バインディングを作成した、と言うよりもバインディングを生成するルールを
>> > 記述した、と言う方が事実を反映しているかも知れません)
> Haskellはこうやってバインディングを作るんですねぇ。
>
> SWIGとかと同じアプローチですね。
> と思ったんですがそうでもないのかしら。途中で.cを作らないっぽ
> いですね。FFIでGroongaのCのAPIを呼び出しているっぽいですね。
> Gaucheのアプローチに近そう。
じつはHaskellには何個かFFIを使ったライブラリの作り方があるんですよ。

Haskellは実に様々な選択肢を提供します。
ひとつはRuby-GNOME2のように人力でコードを書く方法です。
これは何と言っても王道で、これができないと自動生成したものが正しいかどう
かなんて判断できませんものね。

次はc2hsで書く方法です。
http://www.skybluetrades.net/blog/posts/2013/09/22/c2hs-and-haskell-ffi.html
にありますが、これはどうやらC->Haskellへの変換ルールを書いてやるもののよ
うです。
これはいく分か楽にFFIをするのを楽にしてくれるようです。
(ようです、と書いたのはこれを使っているライブラリを使ったことはあるものの、
実際に使ってライブラリを書いたことがないためです。)

次はc2hsc+hsc2hsを使う方法です。
これはHaroongaを書くのに使った方法で、Cから一旦hscという中間形式を経由し
てhsc2hsでHaskellのコードに変換してやる 方法です。この方法だと80%〜90%ほ
どの変換作業を自動化できます。
後の残りはヘッダーにdefineされているマクロをHaskellの世界に持っていくか
や、C言語の構造体へのアクセスの方法を提供するかしな いかの選択です。
>> > 唯一目立った制限があるとしたらgrn_obj構造体へのHaskellからの内部アクセス
>> > 方法です。
>> > GroongaのC APIの解説記事(と言っても少ないですが)を見る限り、「grn_obj
>> > 構造体は汎用ポインタ型でよしなにしてくれる」という事からアクセスの手段を
>> > バ インディングからは提供しない、としました。
> grn_obj->u.vとかしないってことですよね?
> よいと思います。
それがこの部分に該当します。言葉が足りなかったようですね。すいません。。。
> grn_obj->headerはリードオンリーで触ってもよいやつなんですが、
> 低レベルの操作(*)をしなければ必要になることはないと思うので、
> 大丈夫だと思います。
>
> (*) (Groongaの世界の)オブジェクトの型によって処理を振り分けるとか
むむっ、C APIを使えばそこまで小回りが効くようになるんですね!
そのうちHaroongaをどうやって作ったかについてブログに書こうとしているんで
すが、中々筆が進まなくて…。
>> > その他、現時点ではもう少しとっつきやすくする為のGroonga.SimpleAPIモ
>> > ジュールを提供しています。これはGroongaの GObject-Introspectionを用いた
>> > Qiitaの記事( http://qiita.com/groonga/items/71b145b37d77bd160bf2 )にある
>> > ようなアクセス方法に似せたAPIを提供します。
> Groongaコマンド(selectとかstatusとか)を使えるレイヤーのAPI
> ということですね。groongaコマンド(実行ファイルの方)でできる
> ことと同じことができるので、たしかにとっつきやすそうですね!
>
> Simpleだと「どう使えるか」はわかるのですが、「何ができるのか」
> はわかりずらいので、もしかしたら、Groonga.CommandAPIとか
> Groonga.QueryAPIとかにした方がよいかもしれませんね。
そうですね!ありがとうございます。
仰る通り、Simpleだと確かにどう使えるかはわかるんですが、
何が出来るかが把握できないのでCommandAPIにしました!

また、もうすこしHaskellらしくするためにCommandAPIのAPIの関数の型を単なる
Stringではなく、Command型や Database型を関数の引数の型に使ってやることに
しました。ユーザー定義型が組み込み型に比べて少ない機能を提供するC系の言
語では出てこ ない発想だと思うので解説します。

Haskellのような型を更に拡張して代数的データ型を定義できる言語では、ユー
ザー定義型と組み込み型の区別がありません(厳密に言えばある とは思います
が、C言語やC++に比べれば無いに等しいです)。

その為、関数の名前・引数の名前だけが何が出来るのか、の目印になるとは限ら
なくなります。
もちろん、このような機能が無くても良いソフトウェアは書けますし、無くても
良いと思うかも知れません。
ですが、型になると嬉しいことがあります。それは、コンパイラによる静的な解
析の対象になります。
つまり、テストを頑張って書いたりとか、良い名前を決めるのに悩んでいた時間
を少しばかり動くコードに回すことが出来るのです!

そして、コンパイル時により高度な型チェックが出来るようになります。それを
応用したものに、RubyでいうRailsのフレームワークの位置づ けにあるYesodと
いうフレームワークがあるんですが、それのDBのバックエンドにはPersistentと
いうフレームワークが使われていま す。これはDBをDSLから使っているのです。
HaskellでDSL?と思うかも知れません。
DSLとはDomain Specific Languageですね。どこにもインタプリタで動的に生成
するものである、という定義は無いわけです!
今までの静的型付き言語ではコンパイル時にDSLを扱う機能のサポートが少な
かったようなのです。

なぜ、このような話をしたかというと、CommandAPIを選択してQueryAPIの名前を
選択を選択肢なかったかの理由を述べるためです。
QueryAPIというと、Relationを扱うという意味が入ってしまうかな、と思ったた
めです。更にいうと、コンパイル時のDSLを使って クエリーを生成するAPIか
な、と勘違いしそうだと思ったためです。

Haskellの布教みたいになってしまいましたね。普段とは違ったパラダイムの言
語に触れてみるのも面白いですよ、という事にして締めます。 (目を逸らしつつ)

> # groonga-gobject、リリースしないと。。。
あらー、まだ未リリースだったんですね。
面白い試みだと思いますし、GObject-introspectionの仕組みを使っているGTK以
外では数少ないライブラリだと思うのでリ リースを楽しみにしてます!




groonga-dev メーリングリストの案内
Back to archive index