0Pricing
Learn Rust Coding · レッスン

外部関数インターフェース(FFI)

FFIを使ってRustからCライブラリを呼び出し、他の言語から利用できるRust関数を公開する方法を学びます。

「外部関数インターフェース(FFI)」はCoddyKit上の無料Learn Rust Codingレッスンです。 これはレッスン1/3です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLearn Rust Coding学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Learn Rust Codingコースには全3レッスンが含まれています。

FFIとは何か

FFIはForeign Function Interface(外部関数インターフェース)の略です。あるプログラミング言語で書かれたプログラムから、別の言語で定義された関数を呼び出したり、データ構造を利用したりするための仕組みです。

Rustでは、FFIを使って他の言語、特にCで書かれたコードと連携できます。既存のライブラリやシステムAPIと統合する際に非常に役立ちます。

FFIを使う理由

FFIは日常的に使うツールではありませんが、次のような場合に強力な力を発揮します。

  • 既存のCライブラリを活用する:高性能で成熟したライブラリの多くはC/C++で書かれています。FFIを使えば、Rustから直接利用できます。
  • システムAPI:Cインターフェースしか提供されていない可能性のある、オペレーティングシステムの機能と連携できます。
  • 相互運用性:他の言語(Python、Java、またはNode.js経由のJavaScriptなど)から呼び出せるRustライブラリを構築できます。

RustからCを呼び出す:宣言

RustからC関数を呼び出すには、まずextern "C"ブロックを使ってそのシグネチャを宣言する必要があります。これにより、実装を記述しなくても、C関数の形式をRustに伝えられます。

"C"の部分はCの呼び出し規約を指定し、関数呼び出しに互換性があることを保証します。

extern "C" {
    // Declare C functions here
    // Example: int puts(const char *s);
    fn puts(s: *const std::os::raw::c_char) -> std::os::raw::c_int;
    // Example: int add(int a, int b);
    fn add(a: std::os::raw::c_int, b: std::os::raw::c_int) -> std::os::raw::c_int;
}

RustからCを呼び出す:`unsafe`ブロック

Rustの基本的な約束はメモリ安全性です。しかし、FFIを介してCコードと連携する場合、Rustは外部コードの安全性を保証できません。

そのため、extern "C"ブロックで宣言したC関数の呼び出しは、必ずunsafeブロックで囲む必要があります。これは、安全性の保証を維持する責任が自分(および他の開発者)にあることをコンパイラーに示すものです。

extern "C" {
    // We're declaring that a C function `puts` exists.
    fn puts(s: *const std::os::raw::c_char) -> std::os::raw::c_int;
}

fn main() {
    let rust_string = "Hello from Rust via C!";
    // C strings need to be null-terminated.
    let c_string = std::ffi::CString::new(rust_string).expect("CString failed");

    unsafe {
        // Calling the C 'puts' function. This requires 'unsafe'.
        puts(c_string.as_ptr());
    }
    println!("C function call demonstrated.");
}

型のマッピング:RustからCへ

FFIを使う場合、Rustの型がCの型に正しく対応していることを確認する必要があります。Rustでは、この目的のためにstd::os::rawとstd::ffiに専用の型が用意されています。

  • i32 -> std::os::raw::c_int
  • f32 -> std::os::raw::c_float
  • bool -> std::os::raw::c_uchar(または同等の型。Cには標準のブール型がありません)
  • &str -> *const std::os::raw::c_char(C文字列にはNULL終端が必要で、通常はstd::ffi::CStringで処理します)
  • &mut [T] -> *mut T

未定義動作を避けるため、必ずこれらの明示的なC型を使用してください。

例:Cの`add`関数を呼び出す

int add(int a, int b);という関数を持つCライブラリがあるとします。Rustからは次のように呼び出します。整数型にc_intを使用している点に注目してください。

(このコードはFFIの構文を示すものです。外部でコンパイルしたCライブラリをリンクしないと実行できません。)

extern "C" {
    // Declaration of the C function `add`
    fn add(a: std::os::raw::c_int, b: std::os::raw::c_int) -> std::os::raw::c_int;
}

fn main() {
    let x = 10;
    let y = 20;

    let result = unsafe {
        // Call the C 'add' function within an unsafe block
        add(x as std::os::raw::c_int, y as std::os::raw::c_int)
    };

    println!("Attempted to call C add. Result (if linked): {}", result);
}

RustをCに公開する:基本

Rustの関数をCから呼び出せるようにするには、次の2つが必要です。

  1. #[no_mangle]:この属性は、Rustコンパイラーが関数名を「マングリング」(変更)するのを防ぎます。Cコンパイラーは、単純でマングリングされていない名前を想定します。
  2. extern "C":関数がCの呼び出し規約を使用するよう指定し、Cとの互換性を確保します。

例:C向けのRust関数

これは合計を計算し、Cプログラムから呼び出せるRust関数です。#[no_mangle]とextern "C"属性に注目してください。

(このコードはC向けのライブラリとしてコンパイルするよう設計されていますが、この環境で内部テストを行うためにmainも含まれています。)

#[no_mangle]
pub extern "C" fn rust_add_and_print(
    a: std::os::raw::c_int,
    b: std::os::raw::c_int
) -> std::os::raw::c_int {
    let sum = a + b;
    println!("Rust function received: {} + {} = {}", a, b, sum);
    sum
}

fn main() {
    println!("This Rust code exposes a function for C.");
    // We can also call it internally for demonstration
    let result = rust_add_and_print(5, 7);
    println!("Internal call result: {}", result);
}

FFIのメモリ管理

FFIの境界をまたぐメモリ管理は非常に重要です。Rustがメモリ(文字列など)を確保してCにポインターを渡す場合、C側はデータをコピーするか、正しく解放する責任を負う必要があります。

反対に、Cがメモリを確保してRustにポインターを渡す場合、明示的に指示されない限り、Rustはそのメモリを解放してはいけません。あるいは、データをコピーする必要があります。

std::ffi::CStringやCStrなどのツールは、NULL終端を処理し、所有権の適切な移転を保証することで、C互換文字列を安全に管理するのに役立ちます。

FFIの理解度チェック

RustのForeign Function Interfaceについての理解度を確認しましょう。

FFI:異なる世界をつなぐ橋

RustのForeign Function Interfaceについて学びました。

FFIを使うと、Rustは真に強力な相互運用性を備え、次のことができるようになります。

  • extern "C"とunsafeブロックを使って、Cライブラリの関数を呼び出す。
  • #[no_mangle]とpub extern "C"を使って、Rustの関数を他の言語に公開する。
  • std::os::rawの型を使って、型のマッピングを慎重に処理する。

FFIはRustをさまざまなエコシステムに統合するための強力なツールです。ただし、特に安全性とメモリ管理について、慎重に扱うことが重要です。

よくある質問

「外部関数インターフェース(FFI)」レッスンは無料ですか?

はい。「外部関数インターフェース(FFI)」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Learn Rust Codingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Learn Rust Codingコースには全3レッスンが含まれています。

「外部関数インターフェース(FFI)」で何を学びますか?

FFIを使ってRustからCライブラリを呼び出し、他の言語から利用できるRust関数を公開する方法を学びます。 ブラウザで直接実行するハンズオンコードでLearn Rust Codingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Learn Rust Codingを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのLearn Rust Codingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/3です。

「外部関数インターフェース(FFI)」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このLearn Rust Codingレッスンでコードを書いて実行できますか?

はい。すべてのLearn Rust Codingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 外部関数インターフェース(FFI)
  2. RustからWebAssembly(WASM)へ
  3. ベンチマークとパフォーマンスチューニング
← Learn Rust Codingに戻る