$30 off During Our Annual Pro Sale. View Details »

他言語がメインの場合のRustの活用法 - csbindgenによるC# x Rust FFI...

他言語がメインの場合のRustの活用法 - csbindgenによるC# x Rust FFI実践事例

Rust.Tokyo 2023
https://rust.tokyo/2023/

Yoshifumi Kawai

October 21, 2023
Tweet

More Decks by Yoshifumi Kawai

Other Decks in Technology

Transcript

  1. About Speaker 河合 宜文 / Kawai Yoshifumi / @neuecc Cysharp,

    Inc. - CEO/CTO 株式会社Cygamesの子会社として2018年9月設立 C#関連の研究開発/OSS/コンサルティングを行う Microsoft MVP for Developer Technologies(C#) since 2011 CEDEC AWARDS 2022エンジニアリング部門優秀賞 .NETのクラスライブラリ設計 改訂新版 監訳 50以上のOSSライブラリ開発(UniRx, UniTask, MessagePack C#, etc...) C#では世界でもトップレベルのGitHub Star(合計30000+)を獲得
  2. 原則なんでもC#でやる、が…… ネイティブコードを利用すべき状況がある ・Android NDKなどネイティブAPIしかないものを利用したい ・Cなどで作られているネイティブライブラリを利用したい C++使う? C++は(特にクロスプラットフォームビルドが)厳しい…… あと普通にC++書きたくない(?) Pure C#で移植する?

    モノによってはあまりにも大変すぎる…… (パフォーマンス面ではC#に満足しているため、それは理由にない) (コード共有などの面も、クライアントもサーバーもWASMも全部C#でやるため普通に共有できている)
  3. 救いの手、Rust ネイティブコードの選択肢 C++ or Rust まともな標準パッケージマネージャー C++は無 十分な開発環境(rust-analyzer, RustRover) 総合的にはVisual

    Studio 2022でC++のほうが強力かも 特にRustのデバッガー周りはかなり不満はある cargo buildのクロスプラットフォームコンパイル めっちゃサクッとできる、すごい!!! cc / cmakeクレートによる既存Cライブラリとの連携 ビルドが全てRustで完結できて楽ちんすぎて、すごい!! bindgenによるC->Rust自動生成 めっちゃ安定して生成できて、すごい!!!
  4. 救いの手、Rust ネイティブコードの選択肢 C++ or Rust まともな標準パッケージマネージャー C++は無 十分な開発環境(rust-analyzer, RustRover) 総合的にはVisual

    Studio 2022でC++のほうが強力かも 特にRustのデバッガー周りはかなり不満はある cargo buildのクロスプラットフォームコンパイル めっちゃサクッとできる、すごい!!! cc / cmakeクレートによる既存Cライブラリとの連携 ビルドが全てRustで完結できて楽ちんすぎて、すごい!! bindgenによるC->Rust自動生成 めっちゃ安定して生成できて、すごい!!! 総合的にはRustに大満足 言語的に難しいという先入観というか風評があったため 当初かなり躊躇ったのですが、やってみると意外とス ムーズに使えて良かった。C#と似てる部分も多いので (?)C#の人にもお勧め(?) ZigやC# NativeAOTという選択もモノによってはな くはなかったんですが、現在においてRustの完成 度やエコシステムの充実度は群を抜いていた
  5. csbindgen Rust to C# https://github.com/Cysharp/csbindgen bindgen(C to Rust), cbindgen(Rust to

    C)のようにRust to C#(cs) build.rsにコンフィグを書いてコンパイル時 にsynで指定の.rsを解析して.csを生成する 手書きバインディング作成はしんどいけど、生 成系でいいものがなかったので作ってOSS公開
  6. Concept of csbindgen ブラックボックスのないバインディング生成 FFI可能なメソッドをRustで定義すると、1:1対応したC#が吐かれる FFI不可能なものを無理やり中間生成で自動対応させたりはしない SWIGなどが複雑な中間コードを生成するのが嫌だった 凝った自動生成する必要はないのでマクロ(proc-macro)は不採用 元コード(rs)は解析のみで弄らずC#生成 FFIの境界面ではRust,

    C#ともにunsafeなコード Rustなのに安全じゃない! が、それがいい(?) 無理やりRustスタイルで安全にFFIできるように ブラックボックスな生成をするよりも、境界を 超えることを表に出して、安全ではないコード を明示的に書かせたほうがむしろRustっぽくな いか……?境界面の唯一の共通言語はC(安全で はない)なのだから。 境界近辺ではメモリもそれぞれC# で確保したメモリ、Rustで確保し たメモリと違うものが飛び交うの でunsafeに留意して慎重にやる クリーンな世界は一歩外側で クリーンな世界は一歩外側で
  7. MagicPhysX 物理エンジンNVIDIA PhysX 5のC#バインディング https://github.com/Cysharp/MagicPhysX ・GUIアプリケーションの3D部分 ・自作ゲームエンジンへの物理エンジン組み込み ・ディープラーニングのためのシミュレーション ・リアルタイム通信におけるサーバーサイド物理 といった用途に使うことを想定して開発

    NVIDIAの公開しているPhysX 5(C++)ではなく、EmbarkStudioが公 開しているphysx-rsをビルド元に使って、csbindgenでバインディ ングを生成した EmbarkStudioは、EA DICE でBattlefieldなどで使われ ている内製エンジン Frostbiteを作っていた人達 が独立して立ち上げたスタ ジオで、Rustでゲームエン ジンを開発している!
  8. physx-rs C++/Rust is not easy C++のheaderをbindgenに 投げてもうまくいかない cxx/autocxxのような取り 組みもあるけれど…… physx-rsはPhysXに特化して元の

    C++コードからC APIを公開する コードを自動生成して、それを 通してC++とRustを繋げた An unholy fusion of Rust and C++ in physx-rs (Stockholm Rust Meetup, October 2019) https://www.youtube.com/watch?v=RxtXGeDHu0w 非常に良いセッション でしたので必見 そしてMagicPhysXはその成果に相乗 りして、RustからC#をcsbindgenで 自動生成して繋げた physx-rsがなかったら 実現は難しかった!
  9. YetAnotherHttpHandler Unity用のHTTP/2(gRPC)クライアント https://github.com/Cysharp/YetAnotherHttpHandler C#のgRPCはPure C#実装(grpc-dotnet)でサーバー性能も結構良い が、Unityではランタイムが古くクライアントとして動作しない しかしgRPCは使いたい…… そこでhyperとRustlsを使って HTTP/2(gRPC)通信部分をRustで実装 win,

    osx, linux, android, iOS – x64, arm64 C#のバインディング(csbindgen)と C# APIとしての高レベルAPIを提供 0 50000 100000 150000 200000 250000 300000 350000 gRPC Implementation performance(2CPUs) Requests/sec(higher is better) https://github.com/LesnyRumcajs/grpc_bench/d iscussions/354
  10. YetAnotherHttpHandler Unity用のHTTP/2(gRPC)クライアント https://github.com/Cysharp/YetAnotherHttpHandler C#のgRPCはPure C#実装(grpc-dotnet)でサーバー性能も結構良い が、Unityではランタイムが古くクライアントとして動作しない しかしgRPCは使いたい…… そこでhyperとRustlsを使って HTTP/2(gRPC)通信部分をRustで実装 win,

    osx, linux, android, iOS – x64, arm64 C#のバインディング(csbindgen)と C# APIとしての高レベルAPIを提供 0 50000 100000 150000 200000 250000 300000 350000 gRPC Implementation performance(2CPUs) Requests/sec(higher is better) https://github.com/LesnyRumcajs/grpc_bench/d iscussions/354 大部分をPure C#で書く, TLS部分をOpenSSLなどを使うという案があったが、 「Pure C#で書くのは大変」「OpenSSLなどをクロスプラットフォームビル ドするのが大変」といった問題があった。 RustはPure Rustによる素晴らしいライブラリ郡がある&それらはクロスプ ラットフォームビルドがやりやすい&csbindgenはRustからのコード生成を サポートする、といった形によってRustライブラリのC#利用を可能にした
  11. NativeCompressions LZ4 / Zstandardの.NETバインディング (開発が今日までに間に合わなかったのでOSS化はまだ!) ・伸縮が爆速のLZ4 ・バランスよく高性能なZStandard Cライブラリの両者をRustのCC/CMakeでビルドしてcsbindgenを通 してC#から呼び出す 圧縮ライブラリは通常Pure

    C#実装するし、基本的にパフォーマン スも問題ない、のだけれど…… 特にZStandardは頻繁なバージョンアップのたびに性能が向上してい る。C#移植すると、移植時のコードで固定されてしまい、その後の 性能向上の最適化コードにはついていけない、結果、ネイティブラ イブラリと性能が乖離していってしまう。 最高の性能をC#に持ち込むために ネイティブバインディングを選択。 クロスプラットフォームビルドも Rust経由で随分やりやすくなった。
  12. C# ❤ Rust C#の可能性をRustで広げ切り開く C, C++, RustのライブラリをC#に持ち込んで実証した RustはC#/* 任意の言語名を入れてください */

    を補完してくれる csbindgenはよくできてる 自画自賛!作ってよかった! これのお陰でC#とRustの相性が無限大に! syn crateでRustのSyntax Treeを解析するのはやりやすくて快適 C#的には普段Roslyn(C# Compiler)でC#のSyntax Tree解析してるので…… Rust AnalyzerはRoslynで開発されたRed Green Treeを使っていたりなのでより馴染み深い(?) C# ❤ Rustの世界観を深めるため開発していきます……!