Foreign Function Interface (FFI)
Nauczą się Państwo wywoływać biblioteki C z poziomu Rust oraz udostępniać funkcje Rust innym językom za pomocą FFI, zapewniając interoperacyjność.
Foreign Function Interface (FFI) to bezpłatna lekcja Learn Rust Coding na CoddyKit. To lekcja 1 z 3. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Learn Rust Coding, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Learn Rust Coding zawiera 3 lekcji w sumie.
Czym jest FFI?
FFI to skrót od Foreign Function Interface (interfejs funkcji obcego języka). Jest to sposób, dzięki któremu programy napisane w jednym języku programowania mogą wywoływać funkcje lub używać struktur danych zdefiniowanych w innym języku.
W Rust FFI pozwala na interakcję z kodem napisanym w innych językach, najczęściej w C. Jest to szczególnie przydatne podczas integrowania istniejących bibliotek lub systemowych interfejsów API.
Dlaczego warto używać FFI?
FFI nie jest narzędziem używanym na co dzień, ale okazuje się bardzo przydatne, gdy trzeba:
- Wykorzystać istniejące biblioteki C: Wiele wydajnych i dojrzałych bibliotek napisano w C/C++. FFI pozwala używać ich bezpośrednio w Rust.
- Korzystać z systemowych interfejsów API: Wchodzić w interakcje z funkcjami systemu operacyjnego, które mogą udostępniać interfejs wyłącznie w języku C.
- Zapewnić interoperacyjność: Tworzyć bibliotekę Rust, z której można wywoływać funkcje w innych językach, takich jak Python, Java czy JavaScript za pośrednictwem Node.js.
Wywoływanie C z Rust: deklaracja
Aby wywołać funkcję C z Rust, należy najpierw zadeklarować jej sygnaturę za pomocą bloku extern "C". Informuje on Rust, jak wygląda funkcja C, ale nie zawiera jej implementacji.
Część "C" określa konwencję wywoływania C, dzięki czemu wywołania funkcji są kompatybilne.
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;
}Wywoływanie C z Rust: blok `unsafe`
Podstawową obietnicą Rust jest bezpieczeństwo pamięci. Jednak podczas interakcji z kodem C za pośrednictwem FFI Rust nie może zagwarantować bezpieczeństwa obcego kodu.
Dlatego każde wywołanie funkcji C zadeklarowanej w bloku extern "C" musi być opakowane w blok unsafe. Sygnalizuje to kompilatorowi i innym programistom, że za spełnienie gwarancji bezpieczeństwa odpowiada osoba wywołująca.
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.");
}Mapowanie typów: Rust na C
Podczas korzystania z FFI należy upewnić się, że typy Rust są prawidłowo mapowane na typy C. Rust udostępnia w tym celu specjalne typy w modułach std::os::raw i std::ffi.
i32->std::os::raw::c_intf32->std::os::raw::c_floatbool->std::os::raw::c_uchar(lub podobny typ, ponieważ C nie ma standardowego typu logicznego)&str->*const std::os::raw::c_char(ciągi C muszą być zakończone bajtem null; często obsługuje tostd::ffi::CString)&mut [T]->*mut T
Zawsze należy używać tych jawnych typów C, aby uniknąć niezdefiniowanego zachowania.
Przykład: wywoływanie funkcji C `add`
Załóżmy, że mamy bibliotekę C z funkcją int add(int a, int b);. Oto sposób jej wywołania z Rust. Proszę zwrócić uwagę na użycie c_int dla typów całkowitoliczbowych.
(Ten kod demonstruje składnię FFI, ale nie uruchomi się bez skompilowanej biblioteki C dołączonej zewnętrznie.)
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);
}Udostępnianie Rust dla C: podstawy
Aby funkcję Rust można było wywoływać z C, potrzebne są dwie rzeczy:
#[no_mangle]: Ten atrybut zapobiega „manglowaniu” (zmianie) nazwy funkcji przez kompilator Rust. Kompilatory C oczekują prostych nazw bez manglingu.extern "C": Określa, że funkcja ma używać konwencji wywoływania C, dzięki czemu będzie kompatybilna z C.
Przykład: funkcja Rust dla C
Oto funkcja Rust obliczająca sumę, którą można wywołać z programu C. Proszę zwrócić uwagę na atrybuty #[no_mangle] i extern "C".
(Ten kod jest przeznaczony do skompilowania jako biblioteka dla C, ale zawiera funkcję main do testów wewnętrznych w tym środowisku.)
#[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);
}Zarządzanie pamięcią w FFI
Zarządzanie pamięcią na granicach FFI ma kluczowe znaczenie. Jeśli Rust zaalokuje pamięć, na przykład dla ciągu znaków, i przekaże wskaźnik do C, kod C musi albo skopiować dane, albo prawidłowo odpowiadać za ich zwolnienie.
Odwrotnie, jeśli C zaalokuje pamięć i przekaże wskaźnik do Rust, Rust nie powinien jej zwalniać, chyba że zostanie do tego wyraźnie upoważniony; w przeciwnym razie musi skopiować dane.
Narzędzia takie jak std::ffi::CString i CStr pomagają bezpiecznie obsługiwać ciągi znaków kompatybilne z C, zajmując się zakończeniem bajtem null i zapewniając prawidłowe przekazanie własności.
Szybki sprawdzian z FFI
Sprawdźmy Państwa zrozumienie interfejsu funkcji obcego języka w Rust.
FFI: most między światami
Zapoznali się Państwo z interfejsem funkcji obcego języka w Rust!
FFI pozwala Rust stać się prawdziwie wszechstronnym narzędziem interoperacyjności, umożliwiając:
- Wywoływanie funkcji z bibliotek C za pomocą
extern "C"i blokówunsafe. - Udostępnianie funkcji Rust innym językom za pomocą
#[no_mangle]ipub extern "C". - Staranne mapowanie typów przy użyciu typów z
std::os::raw.
FFI to potężne narzędzie do integrowania Rust z różnorodnymi ekosystemami, ale należy pamiętać o ostrożnym użyciu, zwłaszcza w kwestii bezpieczeństwa i zarządzania pamięcią!
Często zadawane pytania
Czy lekcja „Foreign Function Interface (FFI)” jest bezpłatna?
Tak — pełny tekst „Foreign Function Interface (FFI)” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Learn Rust Coding, przejdź na CoddyKit PRO. Kurs Learn Rust Coding zawiera 3 lekcji w sumie.
Co nauczysz się w „Foreign Function Interface (FFI)”?
Nauczą się Państwo wywoływać biblioteki C z poziomu Rust oraz udostępniać funkcje Rust innym językom za pomocą FFI, zapewniając interoperacyjność. Ćwiczysz Learn Rust Coding z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Learn Rust Coding?
Nie wymagamy żadnego doświadczenia. Learn Rust Coding w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 3.
Ile czasu zajmuje lekcja „Foreign Function Interface (FFI)”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Learn Rust Coding?
Tak. Każda lekcja Learn Rust Coding zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Foreign Function Interface (FFI)
- Rust i WebAssembly (WASM)
- Benchmarking i dostrajanie wydajności