読者です 読者をやめる 読者になる 読者になる

プログラミングの魔物

エラー、バグ、仕様変更と戦うブログ

luaの汎用グルーコード

luabindを使おうとした所、LLVMでは動かすのに一苦労&最近更新されていないようなので、簡単な汎用グルーコードを書いてみることにした。
C++11のラムダ式を使えば書けそうだ! と軽く考えてやってみる。


まずグルーコードをラムダ式で置き換える。
しかしラムダ式でグルー化したい関数をキャプチャすると

 No matching function

となりコンパイルが通らない。

理由:変数のキャプチャをするラムダ式は、関数ポインタに変換できないから。
http://togetter.com/li/53940


そこで、関数オブジェクトを関数のポインタに適合させる方法を調べてみる。
検索した中にラムダ式を使うやり方があったので、その方法でキャプチャ済みラムダ式を関数ポインタに変換することにした。

☆関数オブジェクトを関数ポインタに変換する方法。
ラムダ式の特性を利用する。ラムダ式は以下の性質を持つ

  • ラムダ式( []{} )は複数定義された場合でも各々一意な型を持つ。
  • キャプチャしないラムダ式は関数ポインタに変換できる。
  • 外のスコープにあるstaticな変数を参照できる。

空のラムダ式をテンプレート引数に取る一意なテンプレートを作成し、クラステンプレートで関数オブジェクトを保持して、キャプチャをしないラムダ式にstatic経由で渡すことにより、理想的な(関数オブジェクトを保持した状態で関数ポインタに変換可能な)ラムダ式を得ることができる。

あとは引数の数・型、戻り値の型に応じたテンプレートを用意すればいい。
今日のところは暫定的なオーバーロードを書いておく。気になる部分はluabindのソースで参考になりそうなコードを見つけて改善しよう。

ということで一応汎用グルーコードを動かすことができた。
ただしC++11の機能に依存しているので、開発環境によっては苦労するだろう。
それにしてもラムダ式、便利。


今回は関数のみの公開だったので、簡単な仕組みにすることができた。
しかし、クラスをLuaへ公開する場合はもっと複雑になるだろう。
今後はC++/Lua間でのクラス公開の仕様も調べていきたい。