OCamlでSDLのバインディング
最近、ちょっと思うことがあってOCamlでSDLのバインディングを作ってみています。OCamlでCの連携を書くのはもちろん初めてなので・・・というか何かの言語でCのバインディングを書くというのは初めてです。基本便利に使わせてもらってる方でしたので。
他の言語はどうかはほとんど知りませんが、OCamlでは結構Cとの連携は書きやすいと思います。書きやすいというか、基本がシンプルなのでわかりやすい、という方が正しいでしょうか。
OCamlのCバインディングについては、18.CとObjective Camlのインタフェース にほとんど書いてあります。が、こいつが全編英語ですので、有用な日本語情報はこちらが詳しいです。
さて、OCamlでのSDLバインディングですが、githubで作っています。sdlcaml
ただしこれは基本的に自分で使う用に作っているので、他の方には決してオススメするようなものではありません。現在はとりあえずEvent回りまで実装していますが、JoystickとかAudioとかは実装してませんし、いずれ実装する予定のOpenGL部分には手すらつけていません。
ちなみに一般的なSDLのOCamlバインディングは、OCamlSDLです。皆さんOCamlでSDLを使う場合はこちらを使いましょう。
ある程度実装したところで、実際にやってみないとわからなかった部分を挙げてみます。
- OCaml側のレコードが深いとFieldの連鎖がめんどくさい。
- 引数無ヴァリアントと引数有ヴァリアントが一つの型に混ざってるとめんどくさい。
- ヴァリアント毎の変換を用意しないとならない
- Val_intとInt_valなど、相互変換がかならず必要
- 基本的な部分しか用意されていないため、リストとかを構成するためにも一々自分でなんとかしないとならない。
特に、Fieldの絡みがめんどくさいです。今自分が書いているFieldがどの部分にあたるのか、というのがよくわからなくなって、実際に動かしてみたらSegmentation Fault、というのを何度もやらかしました。ocamldebugというのが強力だとはよくわかりました。ocamloptだけじゃなく、バイトコンパイルのもの(.run)も作っておいた方がいいと学びました。
それと、OCaml自体の開発ポリシーが、便利なものは必要最低限のものしか用意せず、コア言語の部分に注力する、というのがあるようですので、ちょっとした便利ライブラリというのが無いのは仕方無いようですね。
SDL自体はかなりシンプルな作りなので、基本的に1:1でバインディングを作っていくだけなのですが、いかんせん純粋なCですので、OCaml側で表現してみると、かなりC側で色々としてやらないとならないです。その辺はどうしようもないですね。我慢するしかないです。
まだまだ最低限のインターフェースしか無い上、Cとの直接バインディングしか作っていませんし、基本部分はそうして、よりハイレベルなインターフェースはOCaml側で作ろうと考えてます。
ただ、まだどうすればいいのかよくわからない部分があります。SDLではユーザイベントとか、関数ポインタを登録するとかあるのですが、こういう形の関数に、どうやってOCamlの関数渡せばいいんでしょうか。この辺がさっぱりわかりません。下手に渡すとGCが働いたときにアウトになると思いますし、この辺はちょっと調べてもさっぱりでした。どなたが御存じでしたら御教授願えれば幸いです。