C++ との相互運用

Rust コミュニティでは、C++/Rust の相互運用のために複数の選択肢が提供されており、新しいツールも常に 開発されています。現時点で Chromium では、CXX というツールを使用しています。

インターフェース定義言語 (Rust に非常によく似ています)で言語境界全体を記述すると、その後 CXX ツールが Rust と C++ の両方の関数と型の宣言を生成します。

cxx の概要図。同じインターフェース定義を使って C++ 側と Rust 側のコードの両方を作成し、その後それらが最小公分母となる C API を介して通信することを示しています

これの使用方法の完全な例については、CXX チュートリアルを参照してください。

図に沿って説明してください。内部では、これは前に行ったこととまったく同じことを していると説明してください。さらに、このプロセスを自動化することには次の利点が あることを指摘してください:

  • このツールは、C++ 側と Rust 側が一致することを保証します(たとえば #[cxx::bridge] が実際の C++ または Rust の定義と一致しない場合はコンパイル エラーになりますが、同期していない手動バインディングでは未定義動作が発生します)
  • このツールは、C 以外の機能に対する FFI サンク(小さく、C ABI 互換の トップレベル関数)の生成を自動化します(たとえば Rust または C++ の メソッドへの FFI 呼び出しを可能にします。手動バインディングでは、そのような トップレベル関数を手作業で作成する必要があります)
  • このツールとライブラリは、一連の中核となる型を扱えます。たとえば:
    • &[T] は、特定の ABI やメモリレイアウトを保証しないにもかかわらず、 FFI 境界を越えて渡せます。手動バインディングでは std::span<T> / &[T] を 手作業で分解し、ポインタと長さから再構築する必要があります。各言語で 空のスライスの表現がわずかに異なるため、これはエラーを起こしやすいです)
    • std::unique_ptr<T>std::shared_ptr<T>、および/または Box のような スマートポインタはネイティブにサポートされています。手動バインディングでは、 C ABI 互換の生ポインタを渡さなければならず、寿命管理と メモリ安全性のリスクが高まります。
    • rust::StringCxxString 型は、言語間における文字列表現の違いを理解し、 それを保ったまま扱います(たとえば、rust::String::lossy は UTF-8 ではない 入力から Rust の文字列を構築でき、rust::String::c_str は文字列を NUL 終端できます)。