Callback
- Rust kursu
- İleri seviye
- Ders 39/81
- 4 dk
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.
Başlangıç kodu
use std::ffi::{c_int, c_void};
fn main() {
// buraya yaz
}Örnek çözüm
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);
}Beklenen çıktı
[1, 2, 5, 9]
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 Callback içinde panic olursa ne olur?
- Görmezden gelinir
- Rust'a döner
- C sınırını geçemez; program durdurulur (abort) Doğru cevap
- C'ye hata döner
Açıklama: 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.
2 C çağrı kuralı
____ fn kucukten_buyuge(a: *const c_void, b: *const c_void) -> c_int {
0
}
extern "C" fn kucukten_buyuge(a: *const c_void, b: *const c_void) -> c_int {
0
}
Açıklama: C'ye verilecek callback C çağrı kuralıyla tanımlanır.
3 Öğe ve anlamı
| Kavram | 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 |