Kouhei Sutou
kou****@cozmi*****
2008年 5月 12日 (月) 12:25:00 JST
須藤です。 2008/05/10 3:09 <morit****@razil*****>: > 最近SWIGを使いつづけるご利益があまり感じられなくて、 > 次にAPIを拡張するぐらいのタイミングで脱SWIGしようかと思っていたのですが、 > 単に研究が足らなかっただけなのかも‥。ちょっと揺れてます。。 SWIGにはSWIGの利点があると思うのですが、今のような使い方だと残念ながら あまりその利点が活かせていないと思います。なので、今のような使い方を続ける のであれば、SWIGを捨てても問題ないと思います。 私の感覚ではSWIGでうれしいことは以下のようなことです。 * 定数が自動で定義される * エラー処理を一ヶ所で書ける GObjectなどではCでもメタプログラミング的なことができるので、定数を動的に定義 することができますが、普通のCでは手動で静的に定義しないといけません。定数の数 が多いとこれがとても面倒です。例えば、GUIのツールキットでキーボードのキーを定 数で表している場合にそれらを全部手動でRuby側に公開するのはしんどいです。 Cの関数では複数の値を戻り値として返すことができないので、普通の戻り値でエラー かどうかを返して、引数にポインタを渡して値を返すこともそこそこありません。Senna もそうですし、Subversionもそうなっています。このようにエラーの表現のしかたが統 一的に決まっている場合は、エラーチェックを機械的に行うことができます。つまり、 SWIGでできるということです。 ただ、残念ながら今のRubyバインディングのAPIはエラーチェックをプログラマに任せる ようになっています。これによりCやPerl(これは私の偏見)のようなRubyプログラマに は使いづらいAPIになっています。Rubyであれば、エラーチェックはライブラリ側が勝手 にやってくれて、必要なら例外を投げるようにするのが自然だと思います。 (これのパッチは%append_output化が終わったら投げようと思っていましたが。) 一方SWIGの嫌なところを以下の通りです。 * Cのライブラリのバインディングを作るときは、使いやすいAPIを提供するために .rbでSWIGで生成されたものをラップしなくてはいけない。 Cでは名前空間がないので関数名にプレフィックスをつけて分離しますが、Rubyではそれ は使いづらいです。そのため、ClassやModuleを使って名前空間を作り、プレフィックスを 除いたメソッド名にしないといけません。(使いやすいAPIを作るなら) つまり、SWIGで普通にCのライブラリのRubyバインディングを作ったときは、それをラップ する.rbを作らなければいけません。実際、Sennaでもそうしています。 つまり、簡単に言えば思ったより手作業あるね、ということです。 もちろん、.iでclassなどを使って頑張れば.rbでラップしなくてもそれっぽく使いやすいAPIを 作れるかもしれません。 例えば、C++のように名前空間のあるものからバインディングを生成する場合はSWIGがそれ を意識して頑張ってくれるので、Cの場合よりもラップするコードは少なくなると思います。 場合にもよりますが、%renameとか%ignoreとかで頑張れば.rbはほとんど必要なくなるかも しれません。 今のSennaの.iのように%include senna.hしないで.iにコピペしているのであれば、.iの中で classを定義して、そこでオブジェクト指向っぽいAPIを作った方がよいと思います。 この方法は、例えばHyperEstraierのSWIGバインディングが使っています。 というように、残念ながら今のRubyバインディングのやり方は私から見るとSWIGじゃなく てもよいのでは?という感じです。もちろん、やり方を変えればSWIGのよさを取り入れる こともできると思います。もし、私が直すなら、まずはコピペをやめて%include senna.hに します。 つらつらと書きましたが、もしよかったら参考にしてください。