メインコンテンツへスキップ
ここでは、BLAKE3ハッシュ関数の統合を例に、Rustライブラリの統合方法を説明します。 統合の最初の手順は、ライブラリを /rust フォルダーに追加することです。これを行うには、空のRustプロジェクトを作成し、必要なライブラリを Cargo.toml に追加する必要があります。また、Cargo.toml に crate-type = ["staticlib"] を追加して、新しいライブラリが staticlib としてコンパイルされるよう設定する必要もあります。 次に、Corrosion ライブラリを使用して、そのライブラリを CMake にリンクする必要があります。まず、/rust フォルダー内の CMakeLists.txt にライブラリフォルダーを追加します。その後、ライブラリディレクトリに CMakeLists.txt ファイルを追加する必要があります。その中で、Corrosion の import 関数を呼び出します。BLAKE3 を import するには、次の行を使用しました。
corrosion_import_crate(MANIFEST_PATH Cargo.toml NO_STD)

target_include_directories(_ch_rust_blake3 INTERFACE include)
add_library(ch_rust::blake3 ALIAS _ch_rust_blake3)
したがって、Corrosion を使用して正しい CMake ターゲットを作成し、その後でより扱いやすい名前に変更します。_ch_rust_blake3 という名前は Cargo.toml に由来しており、そこではプロジェクト名 (name = "_ch_rust_blake3") として使われていることに注意してください。 Rust のデータ型は C/C++ のデータ型と互換性がないため、この空のライブラリプロジェクトを使って、C/C++ から受け取ったデータを変換し、ライブラリのメソッドを呼び出し、さらに出力データを逆変換するためのシムメソッドを作成します。たとえば、BLAKE3 では次のメソッドを実装しました。
#[no_mangle]
pub unsafe extern "C" fn blake3_apply_shim(
    begin: *const c_char,
    _size: u32,
    out_char_data: *mut u8,
#[no_mangle]
pub unsafe extern "C" fn blake3_apply_shim(
    begin: *const c_char,
    _size: u32,
    out_char_data: *mut u8,
) -> *mut c_char {
    if begin.is_null() {
        let err_str = CString::new("input was a null pointer").unwrap();
        return err_str.into_raw();
    }
    let mut hasher = blake3::Hasher::new();
    let input_bytes = CStr::from_ptr(begin);
    let input_res = input_bytes.to_bytes();
    hasher.update(input_res);
    let mut reader = hasher.finalize_xof();
    reader.fill(std::slice::from_raw_parts_mut(out_char_data, blake3::OUT_LEN));
    std::ptr::null_mut()
}
このメソッドは、C互換の文字列、そのサイズ、出力文字列へのポインタを入力として受け取ります。次に、C互換の入力を実際のライブラリメソッドで使われる型に変換してそれらを呼び出します。その後、ライブラリメソッドの出力を再びC互換の型に変換する必要があります。このケースでは、ライブラリが fill() メソッドによるポインタへの直接書き込みをサポートしていたため、変換は不要でした。ここでの主なアドバイスは、メソッド数をできるだけ少なくすることです。そうすれば、各メソッド呼び出しで必要になる変換が減り、オーバーヘッドも抑えられます。 #[no_mangle] 属性と extern "C" は、この種のすべてのメソッドで必須である点にも注意してください。これらがないと、C/C++互換で正しくコンパイルできません。さらに、これらはインテグレーションの次のステップでも必要になります。 シムメソッドのコードを記述したら、次はライブラリ用のヘッダーファイルを準備する必要があります。これは手動で行うこともできますし、cbindgen ライブラリを使って自動生成することもできます。cbindgen を使用する場合は、build.rs のビルドスクリプトを作成し、cbindgen を build-dependency に追加する必要があります。 ヘッダーファイルを自動生成できるビルドスクリプトの例:
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

    let package_name = env::var("CARGO_PKG_NAME").unwrap();
    let output_file = ("include/".to_owned() + &format!("{}.h", package_name)).to_string();

    match cbindgen::generate(&crate_dir) {
        Ok(header) => {
            header.write_to_file(&output_file);
        }
        Err(err) => {
            panic!("{}", err)
        }
    }
また、C互換の属性にはそれぞれ、属性 #[no_mangle] と extern "C" を使用する必要があります。これがないと、ライブラリが正しくコンパイルされなかったり、cbindgen でヘッダーの自動生成を開始できなかったりします。 これらの手順をひととおり終えたら、小規模なプロジェクトでライブラリをテストし、互換性やヘッダー生成に関する問題がないか確認できます。ヘッダー生成中に問題が発生した場合は、cbindgen.toml ファイルで設定を調整してみてください (テンプレートはこちらです: https://github.com/eqrion/cbindgen/blob/master/template.toml) 。 BLAKE3 の統合時に発生した問題についても、触れておく必要があります。 MemorySanitizer は、Rust の一部の変数が初期化されているかどうかを判別できないため、誤検知を引き起こすことがあります。この問題は、一部の変数についてより明示的に定義した メソッド を記述することで解決されました。ただし、この メソッド の実装は低速であり、MemorySanitizer のビルドを修正するためにのみ使用されます。
最終更新日 2026年6月10日