バインディングの例

CXX では、C++/Rust 境界全体を、.rs ソースコード内の cxx::bridge モジュールで宣言する必要があります。

// 著作権 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

#[cxx::bridge]
mod ffi {
    extern "Rust" {
        type MultiBuf;

        fn next_chunk(buf: &mut MultiBuf) -> &[u8];
    }

    unsafe extern "C++" {
        include!("example/include/blobstore.h");

        type BlobstoreClient;

        fn new_blobstore_client() -> UniquePtr<BlobstoreClient>;
        fn put(self: &BlobstoreClient, buf: &mut MultiBuf) -> Result<u64>;
    }
}

// Definitions of Rust types and functions go here

注目点:

  • これは通常の Rust の mod のように見えますが、#[cxx::bridge] プロシージャルマクロはこれに対して複雑な処理を行います。生成されるコードはかなり高度ですが、それでも最終的には、コード内に ffi という名前の mod が作られます。
  • Rust での C++ の std::unique_ptr のネイティブサポート
  • C++ での Rust スライスのネイティブサポート
  • (上部)C++ から Rust への呼び出しと Rust の型
  • (下部)Rust から C++ への呼び出しと C++ の型

よくある誤解: Rust が C++ ヘッダーを解析している ように見えます が、これは誤解を招きます。このヘッダーは Rust によって解釈されることはなく、単に生成された C++ コードの中で C++ コンパイラのために #include されるだけです。