🚀 BAŞTAN SONA RUST DİLİ BÖLÜM-19: Unsafe Rust ve FFI (Foreign Function Interface) ☣️

🚀 BAŞTAN SONA RUST DİLİ BÖLÜM-19: Unsafe Rust ve FFI (Foreign Function Interface) ☣️

Selamlar! Serimizin 19. bölümüne hoş geldiniz.

Önceki bölümde Rust’ın makro sistemini, `macro_rules!` ile bildirimsel makro yazımını ve Procedural Macros mimarisini detaylarıyla incelemiştik. Bu bölümde ise Rust’ın bellek güvenliği kurallarının bir kısmını devre dışı bırakan **Unsafe Rust** konusunu ve C/C++ gibi dillerle doğrudan iletişim kurmamızı sağlayan **FFI (Foreign Function Interface)** yapısını göreceğiz.

---

☣️ 1. Unsafe Rust Nedir ve Neden İhtiyaç Duyulur? 🛡️🔓

Rust'ın derleyicisi (Borrow Checker) oldukça katıdır. Ancak işletim sistemleri, donanım sürücüleri (drivers), gömülü sistemler veya C kütüphaneleri ile doğrudan çalışırken derleyicinin statik analiz yapamayacağı durumlar oluşur.

İşte bu noktada Rust bize `unsafe` bloğunu sunar.

⚠️ **Kritik Yanılgı:** `unsafe` demek "Borrow Checker kapandı, bellek yönetimi tamamen kontrolsüz" anlamına GELMEZ. Ownership, Lifetimes ve tip denetimleri halen geçerlidir. `unsafe` bloğu size yalnızca 5 özel "süper güç" verir!

#### Unsafe Rust'ın 5 Süper Gücü:
1. Ham işaretçileri (Raw Pointers) dereference etmek (çözmek).
2. `unsafe` fonksiyonları veya metotları çağırmak.
3. Değiştirilebilir statik değişkenleri (`mutable static`) okumak veya değiştirmek.
4. `unsafe` trait'leri uygulamak (implement etmek).
5. `union` alanlarına erişmek.

---

📍 2. Raw Pointers (Ham İşaretçiler: `*const T` ve `*mut T`) 🎯

Rust'taki standart referansların (`&T` ve `&mut T`) aksine, Raw Pointer'lar:
• Aynı anda hem mutable hem immutable olarak aynı adresi gösterebilir.
• `null` veya bozuk (invalid) bellek adreslerini gösterebilir.
• Otomatik bellek temizliği (Drop) mekanizmasına sahip değildir.
• Yaşam süreleri (Lifetimes) derleyici tarafından takip edilmez.

Raw Pointer **oluşturmak** Unsafe DEĞİLDİR; ancak içindeki veriye erişmek (dereference etmek) **UNSAFE**'tir!

fn main() {
let mut sayi = 10;

// Raw Pointer oluşturma (Safe)
let p1 = &sayi as *const i32;
let p2 = &mut sayi as *mut i32;

// Raw Pointer dereferencing (Unsafe!)
unsafe {
println!("p1 değeri: {}", *p1);
println!("p2 değeri: {}", *p2);
*p2 = 20;
println!("Yeni değer: {}", *p2);
}
}

---

⚙️ 3. Unsafe Fonksiyonlar ve Güvenli Soyutlama (Safe Abstraction) 🛠️

Bir fonksiyonun içinde Unsafe işlemler yapılıyorsa ve çağırana belirli şartlar yüklüyorsa `unsafe fn` olarak tanımlanır.

Ancak Rust dünyasındaki en iyi pratik (Best Practice), **Unsafe kodu Safe bir API arkasında soyutlamaktır (Safe Abstraction).**

Örnek: Standart kütüphanedeki `split_at_mut` benzeri güvenli bir fonksiyon yazalım:

use std::slice;

fn guvenli_dilim_bol(dilim: &mut [i32], orta: usize) -> (&mut [i32], &mut [i32]) {
let uz = dilim.len();
let ptr = dilim.as_mut_ptr();

assert!(orta <= uz); // Sınır kontrolü (Safety Check)

unsafe {
(
slice::from_raw_parts_mut(ptr, orta),
slice::from_raw_parts_mut(ptr.add(orta), uz - orta),
)
}
}

fn main() {
let mut v = vec![1, 2, 3, 4, 5, 6];
let (sol, sag) = guvenli_dilim_bol(&mut v, 3);

println!("Sol: {:?}, Sağ: {:?}", sol, sag);
}

---

🌐 4. FFI: C Kütüphaneleri İle İletişim (`extern "C"`) 🔗

Rust, C dili ile ABI (Application Binary Interface) düzeyinde doğrudan uyumludur. C dilinde yazılmış bir fonksiyonu çağırmak veya C'ye Rust fonksiyonu sunmak son derece kolaydır.

### A. C Standart Kütüphanesinden Fonksiyon Çağırmak (Rust -> C):

extern "C" {
// C'deki abs() ve sqrt() fonksiyonlarının bildirimi
fn abs(input: i32) -> i32;
}

fn main() {
unsafe {
// C fonksiyon çağrıları doğası gereği UNSAFE'tir
let sonuc = abs(-42);
println!("C abs() sonucu: {}", sonuc);
}
}

### B. C Diline Rust Fonksiyonu Sunmak (C -> Rust):

// #[no_mangle]: Derleyicinin fonksiyon ismini değiştirmesini (mangling) engeller
// extern "C": C çağırma sözleşmesine (calling convention) uyum sağlar
#[no_mangle]
pub extern "C" fn rust_topla(a: i32, b: i32) -> i32 {
a + b
}

---

🚨 5. Mutable Static Değiştirme ve Global Durum ⚠️

Rust'ta immutable `static` değişkenler güvenlidir. Ancak `static mut` (değiştirilebilir global değişkenler) okumak veya yazmak Data Race riski taşıdığı için **UNSAFE**'tir!

static mut SAYAÇ: u32 = 0;

fn sayac_arttir() {
unsafe {
SAYAÇ += 1;
}
}

fn main() {
sayac_arttir();
unsafe {
println!("Sayaç: {}", SAYAÇ);
}
}

> **Öneri:** Multithreaded uygulamalarda `static mut` yerine her zaman Bölüm 16'da gördüğümüz `Atomic` tipleri (`AtomicU32`) veya `Arc<Mutex<T>>` yapılarını tercih edin.

---

📝 Bölüm Özeti ve Gelecek Bölüm 🔮

Bu bölümde Unsafe Rust’ın kullanım amaçlarını, Raw Pointer'ları (`*const T`, `*mut T`), Unsafe kodları Safe API'ler arkasında soyutlama mantığını ve FFI ile C entegrasyonunu öğrendik.

👉 Bölüm 20'de Bizi Ne Bekliyor?
• Serinin Muhteşem Finali: **Baştan Sona Rust Özeti ve Proje Mimarisi** 🏆
• Gerçek hayat projelerinde Best Practice'ler
• Rust ekosistemi, popüler Crate'ler (Serde, Anyhow, Cl
ap, Reqwest)
• Kariyer ve Rust ile Gelecek Yol Haritası

Sorularınızı konu altından iletebilirsiniz. Serimizin FİNAL bölümünde görüşmek üzere! 🦀✨

🔒 Bu içeriği görmek için giriş yapın

 
Yanıt yazmak için giriş yapmalısınız
Forum özelliklerini kullanmak ve Level 2 üyelik satın almak için hesabınıza giriş yapın.
135,085Konular
3,298,098Mesajlar
326,276Kullanıcılar
hajiaSon Üye
Üst Alt