2016-08-15 40 views
5

std::path::Path verildiğinde, bu değeri null sonlandırılmış std::os::raw::c_char'a dönüştürmenin en doğrudan yolu nedir? (Bir yol alan C işlevlerine geçmek için).Bir Yolu bir * c_char'a dönüştürmenin en doğrudan yolu nedir?

use std::ffi::CString; 
use std::os::raw::c_char; 
use std::os::raw::c_void; 

extern "C" { 
    some_c_function(path: *const c_char); 
} 

fn example_c_wrapper(path: std::path::Path) { 
    let path_str_c = CString::new(path.as_os_str().to_str().unwrap()).unwrap(); 

    some_c_function(path_str_c.as_ptr()); 
} 

Bu kadar çok ara adımdan kaçınmanın bir yolu var mı?

Path -> OsStr -> &str -> CString -> as_ptr() 
+0

Bir 'Yol'un bir C dizesine dönüştürülebileceğini varsaymak doğru değildir. Platformlar farklı kodlamalar kullanabilir ve kullanabilirler; Bu soyutlamalar bu yüzden ilk sırada var. UNIX benzeri sistemlerle sınırlanıyorsanız, ['OsStrExt'] var (https://doc.rust-lang.org/std/os/unix/ffi/trait.OsStrExt.html). – Shepmaster

+0

Ayrıca, C dizelerinin buna gerek duymasa da, UTF-8 olması gereken bir "String" e dönüştüğünüze de dikkat edin. – Shepmaster

cevap

4

Göründüğü kadar kolay değil. Sağlamadığınız bir bilgi parçası var: Hangi kodlama, yolun içinde olmasını bekleyen C işlevidir?

Linux'ta, yollar "sadece" bayt dizileridir (0 geçersizdir) ve uygulamalar genellikle bu kodları çözmeyi denemezler. (Ancak, bunları, örneğin kullanıcıya gösterecek şekilde belirli bir kodlama ile çözmek zorunda kalabilirler; bu durumda, genellikle, UTF-8 kodlamasını kullanan mevcut yerel ayara göre kodunu çözmeyi dener.)

Windows'da, "ANSI" kod sayfası ve "Unicode" (UTF-16) kullanan varyasyonlar kullanan API işlevleri varyasyonları olduğundan daha karmaşıktır. Ayrıca, Windows UTF-8'i "ANSI" kod sayfası olarak ayarlamayı desteklemez. Bu, kütüphane özellikle UTF-8 beklemediği ve yerel şifrelemeye giden yolu dönüştürmediği sürece, UTF-8 kodlu bir yolun aktarılmasının kesinlikle yanlış olduğu anlamına gelir (ancak , yalnızca ASCII karakterleri içeren dizeler için görünmesini sağlayabilir).

(ı diğer platformlarda bilmem, ama zaten yeterince dağınık.) Rust In

, PathOsStr için sadece bir sarıcı. OsStr, dizge gerçekten geçerli UTF-8 olduğunda UTF-8 ile uyumlu olan bir platform bağımlı temsilini kullanır, ancak UTF-8 olmayan dizeler belirtilmemiş bir kodlama kullanır (Windows'da, aslında WTF-8 kullanıyor, ancak bu değil sözleşmeli, Linux'ta olduğu gibi sadece byte dizisidir.

Bir C işlevine giden bir yolu geçmeden önce, dizenin içinde olmasını beklediğini ve kodun Rust kodlamasını eşleşmediğini belirlemelisiniz, bir CString içinde sarmadan önce onu dönüştürmeniz gerekir. . Pas, bir Path veya OsStr'u str'dan başka bir şeye platform bağımsız bir şekilde dönüştürmenize izin vermez. Unix tabanlı hedeflerde OsStrExt özelliği kullanılabilir ve OsStr bayt dilimine erişim sağlar.

Pas OsStr'da to_cstring yöntemini sağlamak için kullanılır, ancak hiçbir zaman kararlı hale gelmemiştir ve davranışın Windows için uygun olmadığı anlaşıldığı için Rust 1.6.0'da kullanımdan kaldırılmıştır (UTF-8 kodlu bir yol döndürdü) ancak Windows API'ları bunu desteklemiyor!).

+2

Locale, linux hakkında sistematik bir tahminde bulunabilir, ancak bu, yol kodlamaları ile gerçekten ilgili değildir. Yollar, 0 dışında isteğe bağlı baytlar olabilir. – bluss