Rust’ta C-variadic fonksiyon tanımı, her ABI’de çalışan genel bir özellik değildir; desteklenen ABI ve hedef mimari birleşimine bağlıdır. Doğru sınırı bilmek, derleme hatasını ve FFI uyumsuzluğunu önler.
Bu yazı, önce hangi ABI’lerin variadic tanıma izin verdiğini, sonra hangi hedeflerde bu desteğin geçerli olduğunu ve son olarak güvenli kullanım kurallarını ayırarak anlatır. Böylece aynı özelliğin extern blok bildirimi ile gerçek fonksiyon tanımını karıştırmadan ilerleyebilirsiniz.
Bu yazı, önce hangi ABI’lerin variadic tanıma izin verdiğini, sonra hangi hedeflerde bu desteğin geçerli olduğunu ve son olarak güvenli kullanım kurallarını ayırarak anlatır. Böylece aynı özelliğin extern blok bildirimi ile gerçek fonksiyon tanımını karıştırmadan ilerleyebilirsiniz.
Rust’ta C-variadic tanımı nerede geçerlidir?
Variadic fonksiyonlar Rust’ta yalnızca dış arayüzlerde kullanılır; normal Rust fonksiyonları variadic olamaz. Resmî referans,extern ABI’sinin variadic olabilmesi için belirli ABI'derle sınırlı olduğunu ve işaret edilen ABI dışına çıkılamadığını söyler. Ayrıca fn türü düzeyinde de variadic olabilmek için dış ABI’nin izin verilen ABI'den biri olması gerekir.ABI sınırını doğru okumak
Rust referansına göre variadic tanım için temel çerçeve C ailesi ABI’leridir;C ve cdecl güvenli taraftaki ana örneklerdir. system ABI’si ise platforma göre C ile eşlenebilir; Windows’ta variadic davranışın özel eşleşmesi ayrıca belirtilir. Bu yüzden “Rust function item” değil, “extern ABI’li fonksiyon” zihniyetiyle düşünmek gerekir.Bildirim ile tanımı ayırmak
Extern blokta variadic bildirim yapılabilir; gerçek fonksiyon tanımıysa hedef ve ABI desteğine tabidir. Referans,... işaretinin yalnızca dış blok fonksiyonlarının son parametresi olabileceğini belirtir. Bu ayrım önemlidir çünkü bir başlık dosyasını modelleyen bildirim geçerli görünse bile, hedefte gerçek tanım desteklenmeyebilir.Hangi hedeflerde derlenir?
Resmî referans, C-variadic fonksiyon tanımlarının hangi hedef mimarilerde kararlı olduğunu ayrıca listeler. Bu listede x86/x86-64, ARM, AArch64, RISC-V’in belirli alt kümeleri, PowerPC aileleri, s390x, wasm32/wasm64 ve bazı diğer hedefler yer alır; bazı hedefler ise açıkça destek dışı kalır. Bu nedenle konu “Rust sürümü var mı?” sorusundan çok “hedef triple bu özelliği destekliyor mu?” sorusudur.Hedef destek yoksa ne olur?
Desteklenmeyen bir hedefte tanım kullanılırsa derleyici hata verir. Bu durum özellikle gömülü ya da özel mimarilerde önemlidir; çünkü aynı kaynak kodu masaüstünde derlenip hedefte kırılabilir. Pratik karar ölçütü, FFI yüzeyini yazmadan önce hedefin destek tablosunu kontrol etmektir.Rust sürümü tek başına yeterli değildir
Son release notları, bazı ABI’lerde variadic tanım desteğinin zaman içinde stabil hale geldiğini gösteriyor. Bu da sadece “Rust kullanıyorum” demenin yetmediği anlamına gelir; aynı sürümde bile hedef ve ABI kombinasyonu sonucu değiştirebilir. Yani sürüm kontrolü, hedef kontrolünün yerine geçmez.Güvenli kullanımda hangi kurallar geçerli?
Variadic fonksiyon tanımlarıunsafe olmalıdır ve async ya da const olamaz. Ayrıca extern blokta safe bildirim kullanılsa bile, bu yalnızca fonksiyonun variadic argümanlara dokunmadığı durumda anlamlıdır. Başka bir deyişle, güvenli görünen imza gerçek çağrı riskini ortadan kaldırmaz.Argüman türü uyumu
Referans, okunanVaList öğesi ile çağrıda geçirilen türün uyumlu olmasını ister. Tam sayılar için boyut uyumu, işaretçiler için hedef tür uyumu önemlidir; aksi durumda tanımsız davranış riski doğabilir. Bu kısım, FFI yazarken “C tarafı zaten anlar” varsayımının doğru olmadığını gösterir.VaList ile köprü kurma
Rust’unVaList tipi, C’nin va_list tipiyle ABI uyumludur. Bu, C’den gelen variadic akışı doğrudan başka bir C fonksiyonuna taşıyan ara katmanlar için yararlıdır. Ancak bu uyumluluk, yalnızca ABI uyumlu hedef ve doğru imza ile anlam taşır.Ne zaman bu yaklaşımı seçmelisiniz?
Eğer karşı tarafta mevcut bir C API’si zaten variadic ise, Rust tarafında çoğu zaman amacı bu API’yi modellemek olur; yeni bir tasarım olarak variadic seçmek ise genelde daha risklidir. Çünkü tür doğrulaması çağrı anında daha zayıftır ve kullanım kurallarını taşıyan kod daha kırılgan olur. Bu yüzden tercih, çoğunlukla “mevcut FFI’yi doğru sarmala” yönünde olmalıdır.Kısa karar kuralı
API C tarafında sabitse ve hedefiniz destekliyorsa variadic tanım mantıklıdır. Yeni bir Rust API tasarlıyorsanız, çoğu durumda sabit imza veya slice/iterator tabanlı bir tasarım daha okunur ve daha güvenlidir. Bu ayrım, sadece derlenebilirlik değil bakım maliyeti açısından da önemlidir.| Kontrol | Anlamı / uygulanacak adım |
|---|---|
| ABI seçimi | Tanım için C / cdecl ve bazı durumlarda system ABI’nin sınırlarını kontrol et; normal Rust ABI variadic olamaz. |
| Hedef mimari | Derleme hedefi C-variadic tanımı desteklemiyorsa kod kabul edilmez; özellikle bazı gömülü/hedef dışı mimarilerde bu sınır geçerlidir. |
| Tanım mı bildirim mi | Tanım tarafında kısıtlar daha sıkıdır; extern blok içindeki bildirim ile gerçek fonksiyon tanımı aynı şey değildir. |
| Güvenlik işareti | Variadic kullanımda fonksiyon tanımları unsafe olmalıdır; çağrının doğru argümanlarla yapılması beklenir. |
| Argüman uyumu | Okunan tür ile çağrıda geçirilen tür uyumlu olmalı; özellikle tam sayı ve işaretçi eşleşmelerine dikkat et. |
| Dönüşümlü kullanım | C’nin va_list akışını Rust’taki VaList ile doğrudan geçirmek, FFI köprüsünü sadeleştirir. |