Rust
Callback
C'den Rust'a callback geçirmeyi öğrenirsin.
Callback
Bazı C fonksiyonları parametre olarak bir fonksiyon işaretçisi alır. Rust tarafında bu işaretçinin türü extern "C" fn(..) -> ..'dir ve gösterdiği fonksiyon C çağrı kuralıyla tanımlanmalıdır. Klasik örnek C'nin qsort'udur:
use std::ffi::{c_int, c_void};
unsafe extern "C" {
fn qsort(
taban: *mut c_void,
adet: usize,
boyut: usize,
karsilastir: extern "C" fn(*const c_void, *const c_void) -> c_int,
);
}
Karşılaştırma fonksiyonu
Callback, aldığı void işaretçilerini bildiği türe çevirir ve C sözleşmesine göre negatif, sıfır ya da pozitif döndürür:
extern "C" fn kucukten_buyuge(a: *const c_void, b: *const c_void) -> c_int {
// SAFETY: qsort yalnızca dizideki i32 elemanlarının adreslerini verir.
let (x, y) = unsafe { (*(a as *const i32), *(b as *const i32)) };
x.cmp(&y) as c_int
}
Ordering'in ayırt edici değerleri -1, 0 ve 1'dir; as c_int bu yüzden doğrudan C'nin beklediği değeri verir.
Uygulama qsort ile sırala
Yukarıdaki qsort bildirimi ve kucukten_buyuge callback'i ile let mut v = [5, 2, 9, 1]; dizisini sırala (v.as_mut_ptr() as *mut c_void, v.len(), size_of::<i32>()) ve {:?} ile yazdır.
Örnek çözümü göster
use std::ffi::{c_int, c_void};
unsafe extern "C" {
fn qsort(
taban: *mut c_void,
adet: usize,
boyut: usize,
karsilastir: extern "C" fn(*const c_void, *const c_void) -> c_int,
);
}
extern "C" fn kucukten_buyuge(a: *const c_void, b: *const c_void) -> c_int {
// SAFETY: qsort yalnızca dizideki i32 elemanlarının adreslerini verir.
let (x, y) = unsafe { (*(a as *const i32), *(b as *const i32)) };
x.cmp(&y) as c_int
}
fn main() {
let mut v = [5, 2, 9, 1];
// SAFETY: işaretçi, adet ve boyut v ile tutarlıdır.
unsafe {
qsort(v.as_mut_ptr() as *mut c_void, v.len(), std::mem::size_of::<i32>(), kucukten_buyuge);
}
println!("{:?}", v);
}
Kendini test et
-
Callback içinde panic olursa ne olur?
- Görmezden gelinir
- Rust'a döner
- C sınırını geçemez; program durdurulur (abort)
- C'ye hata döner
Cevabı göster
C sınırını geçemez; program durdurulur (abort) — extern "C" fonksiyonlarda panic'in yığını C kodundan geri sarması tanımsızdı; artık sınırda abort edilir. Callback'te catch_unwind kullanılabilir.
-
C çağrı kuralı
____ fn kucukten_buyuge(a: *const c_void, b: *const c_void) -> c_int {
0
}
Cevabı göster
extern "C" fn kucukten_buyuge(a: *const c_void, b: *const c_void) -> c_int {
0
}
-
Öğe ve anlamı
- extern "C" fn(..)
- C fonksiyon işaretçisi
- *const c_void
- Türsüz işaretçi
- x.cmp(&y) as c_int
- -1, 0, 1
- size_of::<i32>()
- Eleman boyutu
Sıradaki ders: Drop ve cleanup