}ページHome2016-04-21waifu2xAvisynthをY8に対応させたTweet要望があったので、気分転換に実装して、v0.0.2をリリースした。planeの処理を省けば良いだけだったので。最初のリリースが2015/5/30なので、もうほぼ1年になるのか、というのが衝撃。この実装はwaifu2x-converter-cppとAvisynthのつなぎをしただけで、たいしたことはしていないのだけど、それでも今でもStarされたりするあたり、知名度というものはすごいなぁと思う次第である。チュートリアル的文書を書いたTweetGtk+のRustラッパーであるgtk-rsの入門を書いた:RustとGtk+で開発するGUIアプリケーションほんとはもう少しやるといいことがあるのだけど(GResource、スレッド対応など)、まぁとりあえずここまで書いてあればGUIアプリケーション書いたことある人であれば感じは掴めるのかなと。いうことでRev0.1。(少なくともいまのところは)ニーズはほとんどないと思うけど、やる気があるうちにある程度形にしておかないと絶対書かないので。自分がこれから書いていくアプリケーションを読み進めるにあたっての基礎知識となれば。「メタプログラミングとは」という内容で話してきました。「メタプログラミングって何?イメージがつかない」という話を受けて、イメージをつくようにするのがこの話の目的です。本当はそれぞれの言語のやりかたについて手順を書けばよかったのですが、力つきたので、実際のライブラリから例を持ってくる方向性にしました。話している間はコードや別の資料も見ながら話していたので、このスライド自体というよりは、各スライドでポイントしているライブラリの実装あるいは類似するライブラリの実装を読んでもらうのがイメージをつかみやすいんじゃないかと思います。それぞれの言語でニワカなところがあるので、全方位からツッコミを受けてもおかしくない内容だと思っています。何かあれば補足していきたいのでぜひどうぞ。強いので、はっきりしたstructとCの関数を呼び出すなんていうケースでは、それっぽいstructとexternでの関数の定義を書けば呼び出せる。コールバックもできる。→他言語関数インターフェイスしかし、以下のようなケースではちょっとやりにくい。要はC言語を解釈してもらえると楽だよねという話なので、「Cでラッパー書いてautotoolsだMakefileだなんだかんだ、ようやくつなげる」となるかと思いきや、このようなCラッパーが必要な状況についてもRustには補助がある。今回はそのやりかたについて紹介する。自分が必要だったところがC世界からのコールバック呼び出しだったので、それについても触れる。基本的には、RustのアプリケーションがCライブラリを使うという想定。コールバックなので、行ったり来たりなのだけどね。やりかたの概要やりかたは概ね以下の通り。traitを定義する実際に呼び出す実際のソースはhttps://github.com/sunnyone/rust-bridgesampleに置いてあるので、ソースがあればいいという方はこちらでどうぞ。やりかたラッパー関数の準備Rustから呼び出したい関数を、普通の関数呼び出しにできる形で定義する。本来は何かのコードのラッパーの想定なのだが、そっち側の知識が必要となると話がややこしくなるので、ここでは単なるCソースを例として使う。上記がsrc/bridge.cに置かれているとする。build.rsにCソースのコンパイル方法の指示するここがこの記事のキモ。cargoに、置いたCソースのコンパイル方法を指示する必要がある。Cargo.tomlにビルドスクリプトが「build.rs」にあるよ、ということを指示する。dependenciesに入れる(gccと言っているが、MSVCも対応しているらしい。FFIではほぼ使うのでここで入れておく。上記で定義した「build.rs」に、コンパイラの呼び出しを定義する。Support」を参照。本来ライブラリのリンクの指示も必要だが、ここでは一旦省く。詳しくは上記ドキュメントを参照(下でもすこし触れる)。onlyでのFFIと一緒。externでfnとstructを定義する。opaqueなstructをenumを定義するのがイディオムだそうだ。Cargoの流儀的には、FFIのためのRustらしくない定義はなんちゃら-sysというcrateに定義するほうがそれらしい。この部分だけの差し替えがしやすいから、とのこと。的構造にあわせた呼び出し部を用意する。今回は、コールバックをクロージャでもらい、それを実際のCコールバックから呼ぶ形にした。「外側」と「内側」の2つのstructを作るRust世界のコード用のデータを入れておく「内側」と、その「内側」とC関数からもらったポインタを格納しておく「外側」を用意する。なくてよいが、こうしておくことで「内側」をBox(ヒープ)で持つことが出来、ポインタに変換してC関数のポインタに渡すことができる。git2-rsのsrc/transport.rsでやっていたので参考にした。traitを実装しポインタが自動で捨てられるようにする後始末大事。コールバックとしてC側に渡す関数をexternで定義する今回はライフタイムをRustが持っているので、キャストするだけ。ここでは、Rust側がライフタイムを握っているのでポインタを渡しているが、もしC側がライフタイムを握るようであれば、Box::into_rawとBox::from_rawをうまく使うといいと思う。ライフタイムの制御から外せる。ラッパーを実装あとはffi関数を呼び出すようMyStructにimplする。呼び出しコードを書く実際呼ぶコードはこんなかんじになる。12345mystruct_freeこれでだいたい使えるはず。おまけ:pkg-configでライブラリを参照させる本来ラップする対象があるはずなので、リンク対象やincludeパスを指定する必要がある。crateを使うと、pkg-configの結果を使える。branchで使ってみてある。実際のところは、panicはやっつけなのでちゃんと分岐させたり、pkg-configに関わらず環境変数で設定できるようにしたりと、工夫がされていることが多いので、詳しくはそこらのライブラリのコードを参照。crateはこんな感じ。