Rust/WinRT を試す (その 2)

はじめに

前回記事以降も順調にアップデートがされているようなので改めて調べてみました。

crates.io に登録

https://crates.io/crates/winrt

crates.io に登録されましたので、 Cargo.toml で GitHub の Git を参照するのではなく、 crates.io の登録バージョン指定で参照できるようになりました。

[dependencies]
winrt = "0.7.1"

build.rs 対応

前回記事で

端的に言うとコード補完がほぼききません。これは WindowsAPI 部分が winmd に定義されているためと思われます。

と書いた点が解消されそうな感じになってきました。

bindgen と同じように build.rs でビルド時に winmd から静的なコード生成をします。これにより IDE から binding コードの参照が可能になりました。

現時点では README.md 等にも記載がないのですが、次のようにすることで利用できました。

Cargo.toml の設定

ビルドプロセスで処理するので build-dependencies にも定義が必要になります。

[dependencies]
winrt = "0.7.1"

[build-dependencies]
winrt = "0.7.1"

build.rs の設定

プロジェクト直下 (Cargo.toml と同じ位置) に build.rs を作成し、次のコードを記述します。

winrt::build!(
    dependencies
        os
    types
        windows::data::xml::dom::*
        windows::foundation::*
        windows::ui::*
);

fn main() {
    build();
}

winrt::build マクロの中身は従来の import マクロのものと同じです。

main.rs / lib.rs の設定

コード側には include 定義を記述します。 main.rs か lib.rs の先頭に下記記述を追加します。

include!(concat!(env!("OUT_DIR"), "/winrt.rs"));

import マクロ定義は削除してください。

これで一回ビルドすると binding コードが生成されてエディッター上から参照できるようになります。

f:id:tan-y:20200721005032p:plain

前回を思うと結構感動します。ただ私の環境では VSCode ではうまく参照ができない事も多く、 CLion では全く見えませんでした。この辺りは IDE 側でも対応を進める必要があるのかもしれません。

NuGet 対応

NuGet からの import も可能になったようです。ただこれは若干特殊な操作を必要とします。

これは実装例が winrt-rs 下にあるのでそちらを参照してください。

まず "cargo winrt" というコマンドを使えるようにする必要があります。

$ cargo install cargo-winrt

※ cargo-winrt も crates.io に登録されています

NuGet も build.rs での前処理になるので Cargo.toml の dependencies, build-dependencies に winrt の参照を設定します。また、それに加えて参照する NuGet パッケージの定義もします。

[package.metadata.winrt.dependencies]
"Microsoft.AI.MachineLearning" = "1.3.0"
"Microsoft.Windows.SDK.Contracts" = "10.0.19041.1"

build.rs でも参照する NuGet のパッケージを指定していきます。

winrt::build!(
    dependencies
        nuget: Microsoft.AI.MachineLearning
        nuget: Microsoft.Windows.SDK.Contracts
    types
        microsoft::ai::machine_learning::*
        windows::foundation::Uri
);

ビルドは通常の "cargo build" ではなく、 cargo-winrt を通して "cargo winrt build" で行います。 NuGet の依存解決のために Cargo に拡張を加えたのではないかと思います。これだと IDE 上からショートカットキーでビルド、というわけにもいかなくなってしまうので (この方針で確定なら) IDE 側にも対応が求められそうです。

おわりに

(個人的に) 最大の懸案だった winmd の binding コードへの参照が可能になってきているのでなんとか使えそうになってきたかなあという感じです。開発もアクティブに進められているようなのでこれからも状況を見ていきたいと思います。