Rust’ta c-variadic fonksiyon tanımlamak artık yalnızca “feature açmak” meselesi değil; hangi Rust sürümünü kullandığınız ve hedef mimarinin hangi ABI’yi desteklediği belirleyici olur. Özellikle
Bu yazıda önce tanım desteğinin nerede geçerli olduğunu, sonra hangi ABI ve hedef sınırlara takıldığını ayıracağız. Ardından güvenli kullanım için çağrı tarafında hangi kontrol noktasını zorunlu saymanız gerektiğini göstereceğiz.
Bu ayrım önemli: Rust, dışarıdan gelen variadic fonksiyonu çağırmayı desteklese bile, Rust içinde aynı biçimde fonksiyon tanımlamak her zaman aynı düzeyde mümkün değildir. Özellikle
Buradaki pratik sonuç şu: Tanım yazarken önce ABI adını, sonra o ABI’nin hedefte gerçekten var olup olmadığını kontrol etmelisiniz. Yalnızca “C ile benzer” olması yetmez; Rust derleyicisinin o ABI için c-variadic’i destekleyip desteklemediği ayrıca belirlenir.
Bu yüzden taşınabilir bir FFI katmanı yazarken, c-variadic tanımı için hedefe özel kod yolu ayırmak gerekir. Aynı kaynak kodu farklı triple’larda derlemek, özellik setini de değiştirebilir.
Dolayısıyla yeni soru artık şudur: Kullandığınız ABI destekleniyor mu ve bu ABI sizin hedefinizde variadic tanıma izin veriyor mu? Bu sorunun cevabı çoğu durumda derleyici sürümüne değil, sürüm + hedef + ABI üçlüsüne bağlıdır.
Ayrıca
Bu ayrım, forum okuyucusunun asıl kararını basitleştirir: önce ABI/target desteğini doğrula, sonra gerçekten C uyumluluğu gerekip gerekmediğine bak. Gerekmiyorsa variadic yerine açık parametreli bir Rust tasarımı daha az risk taşır.
system ABI için tanım desteğinin stabilize edilmesi, bazı eski nightly-varsayımları geçersiz kılar.Bu yazıda önce tanım desteğinin nerede geçerli olduğunu, sonra hangi ABI ve hedef sınırlara takıldığını ayıracağız. Ardından güvenli kullanım için çağrı tarafında hangi kontrol noktasını zorunlu saymanız gerektiğini göstereceğiz.
Rust’ta c-variadic tanım desteği ve ABI sınırları
Tanım desteği neyi kapsar?
Rust Reference’a göre c-variadic bir fonksiyonun son parametresi... olur ve bu biçim yalnızca dış blok fonksiyonlarında kullanılabilir. Tanım tarafında bu özelliğin kullanılabildiği yer, fonksiyonun hangi ABI ile yazıldığına ve hedefin bunu destekleyip desteklemediğine bağlıdır. ... parametresi son parametre olmak zorundadır; ondan sonra başka parametre gelemez.Bu ayrım önemli: Rust, dışarıdan gelen variadic fonksiyonu çağırmayı desteklese bile, Rust içinde aynı biçimde fonksiyon tanımlamak her zaman aynı düzeyde mümkün değildir. Özellikle
c_variadic özelliğinin kullanımı ve hangi hedeflerde açıldığı ayrı bir denetim katmanına tabidir.Hangi ABI’ler uygun?
Resmî referans, variadic parametrelerin yalnızca belirli ABI’lerde kullanılabildiğini söyler.C ve cdecl gibi klasik C tabanlı ABI’ler doğal adaylardır; system ABI ise Windows x86_32’de variadic fonksiyonlar için C ile eşdeğer davranır. Bazı platform-özel ABI’lerin de karşılık gelen -unwind sürümleri vardır.Buradaki pratik sonuç şu: Tanım yazarken önce ABI adını, sonra o ABI’nin hedefte gerçekten var olup olmadığını kontrol etmelisiniz. Yalnızca “C ile benzer” olması yetmez; Rust derleyicisinin o ABI için c-variadic’i destekleyip desteklemediği ayrıca belirlenir.
Hedef mimari neden kritik?
Variadic destek, platformdan bağımsız tek bir evrensel özellik değildir. Rust kaynakları, bazı ABI’lerin sadece belirli hedeflerde geçerli olduğunu açıkça gösterir; örneğinfastcall ve thiscall yalnızca x86_32’de vardır, efiapi ise yalnızca x86 ve ARM hedeflerinde kullanılabilir. Bu yüzden “hangi ABI destekleniyor?” sorusu tek başına yeterli değildir; “hangi hedefte destekleniyor?” sorusu da aynı derecede önemlidir.Bu yüzden taşınabilir bir FFI katmanı yazarken, c-variadic tanımı için hedefe özel kod yolu ayırmak gerekir. Aynı kaynak kodu farklı triple’larda derlemek, özellik setini de değiştirebilir.
Rust 1.93 sonrası ne değişti?
Rust release notes, C-style variadic fonksiyon tanımınınsystem ABI için stabilize edildiğini söylüyor. Bu, özellikle Windows tarafında “sistem ABI’siyle tanım yazabilir miyim?” sorusunu netleştirir. Ancak bu stabilizasyon, diğer ABI ve hedef kombinasyonlarının otomatik olarak serbest olduğu anlamına gelmez.Dolayısıyla yeni soru artık şudur: Kullandığınız ABI destekleniyor mu ve bu ABI sizin hedefinizde variadic tanıma izin veriyor mu? Bu sorunun cevabı çoğu durumda derleyici sürümüne değil, sürüm + hedef + ABI üçlüsüne bağlıdır.
Güvenli kullanımda hangi sınırlar var?
Variadic çağrılarda en kritik sınır, beklenen argüman sayısı ve türleriyle gerçek çağrının birebir uyuşmasıdır. Rust Reference, yanlış sayı ya da yanlış türde argüman geçirmenin tanımsız davranışa yol açabileceğini açıkça belirtir. Bu yüzden variadic kullanımı, “esnek imza” değil, yalnızca C ile uyumluluk gerektiğinde başvurulacak özel bir araçtır.Ayrıca
VaList kullanımında ömür ve kaçırma kısıtları vardır; variadic parametre çağrıdan dışarı sızdırılamaz. Bu kural, güvenli soyutlama yazmak isteyenler için önemlidir: variadic veriyi önce normal bir Rust yapısına kopyalamak, sonra işlem yapmak çoğu zaman daha doğru yaklaşımdır.Ne zaman bu yaklaşım doğru seçimdir?
C-variadic tanım, esasen mevcut C ekosistemine uyum sağlamak için kullanılır:printf benzeri API’ler, callback’ler ve mevcut kütüphane imzaları buna dahildir. Rust tarafında yeni bir API tasarlıyorsanız, mümkünse sabit ve tip güvenli bir imza daha iyi seçimdir; variadic ise yalnızca dış dünya zaten bunu zorunlu kılıyorsa anlamlıdır.Bu ayrım, forum okuyucusunun asıl kararını basitleştirir: önce ABI/target desteğini doğrula, sonra gerçekten C uyumluluğu gerekip gerekmediğine bak. Gerekmiyorsa variadic yerine açık parametreli bir Rust tasarımı daha az risk taşır.
| Kontrol | Anlamı / yapılacak adım |
|---|---|
| Tanımın son parametresi | C-variadic işaretleyici ... yalnızca en sonda yer alır; başka parametreler ondan sonra gelemez. |
| Kullanılabilen ABI | Tanım desteği resmî olarak C-style variadic’i destekleyen ABI’lerle sınırlıdır; system ABI Windows x86_32’de variadic için C gibi davranır. |
| Hedef mimari sınırı | Bazı ABI’ler yalnızca belirli hedeflerde geçerlidir; bu yüzden kodu tek başına ABI adıyla değil hedef triple ile birlikte düşünmek gerekir. |
| Güvenli kullanım | Argüman sayısı veya türü beklenenden farklı olursa tanımsız davranış oluşabilir; çağıran taraf ile imza birebir uyuşmalıdır. |
| Tanım ile çağrıyı ayırma | Rust’tan variadic fonksiyonu tanımlamak ile dışarıdaki variadic fonksiyonu çağırmak aynı destek düzeyi değildir; sürüm ve feature durumu ayrı kontrol edilmelidir. |