2014-06-25 7 views
26

Swift'de Standart C Kitaplığı işlevleriyle oynatırken, C dizelerini geçirirken sorunlarına rastladım. Basit bir örnek (sadece sorunu göstermek için)Swift'de C dizeleriyle çalışma, veya: Nasıl Yapılır: UnsafePointer <CChar> - CString'e dönüştürme

char * strdup(const char *s1); 

strdup() dönüş değeri, başka bir strdup() geçirilebilir anlamına gelir

func strdup(_: CString) -> UnsafePointer<CChar> 

olarak Swift maruz, Temel kütüphane işlevi olarak çağrı:

let s1 : CString = "abc" 
let s2 = strdup(s1) // OK, s2 is a UnsafePointer<CChar> 
let s3 = strdup(s2) // error: could not find an overload for '__conversion' that accepts the supplied arguments 

sorum şu: nasıl oluşturulur bir SwiftBir UnsafePointer<CChar>, 'dan 10, bir standart kütüphane fonksiyonu tarafından döndürülen C dizisi başka bir işleve iletilebilir mi? Bulabildiğim

tek yolu (How do you convert a String to a CString in the Swift Language? gelen kullanarak kod) 'dir:

let s2a = String.fromCString(s2).bridgeToObjectiveC().UTF8String 
let s3 = strdup(s2a) 

Ama iki nedenden dolayı bu tatmin edici bulmuyorum:

  • Bu basit için çok karmaşık olduğunu görev.
  • (Esas neden :) Yukarıdaki dönüşümler yalnızca C dizesi geçerli bir UTF-8 dizesiyle çalışır, aksi halde çalışma zamanı istisnasıyla başarısız olur. Ancak bir C dizesi, bir NUL karakteri ile sınırlandırılmış bir rasgele karakter dizisidir.

Açıklamalar/Arka plan: Tabii, Swift String veya amaç-C NSString gibi yüksek seviyeli veri yapılarını kullanarak yüksek seviyede fonksiyonlar tercih edilmektedir. Ancak, Foundation çerçevelerinde tam bir karşılığı olmayan Standart C Kitaplığı'nda BSD işlevleri vardır.

Bu soruna, Accessing temp directory in Swift numaralı telefonu yanıtlamaya çalışırken rastladım. Burada, mkdtemp(), NSFileManager değiştirmenin (bildiğim kadarıyla) olduğu bir BSD işlevidir. yer alır mkdtemp() döner bir UnsafePointer<CChar> bir CString argüman alır NSFileManager fonksiyonu stringWithFileSystemRepresentation geçirilecek.


Güncelleme: Swift içine C-Strings haritalama basitleştirildi çünkü Xcode 6 beta 6 itibariyle bu sorun artık yok. Sadece

let s1 = "abc"  // String 
let s2 = strdup(s1) // UnsafeMutablePointer<Int8> 
let s3 = strdup(s2) // UnsafeMutablePointer<Int8> 
let s4 = String.fromCString(s3) // String 
+5

Anonim downvoter sayesinde bana soruları yanıtlamak için hatırlattı :) –

cevap

17

Swift 1.1 (ya da belki de daha erken) bulunuyor olsa daha iyi C dize köprüleme yazabilirsiniz:

let haystack = "This is a simple string" 
let needle = "simple" 
let result = String.fromCString(strstr(haystack, needle)) 

CString tip tamamen gitmiş.

+0

Merhaba Nate, cevabınız için teşekkürler. 'st.withCString ({$ 0})', kesinlikle bridgeToObjectiveC(). UTF8String'den daha zariftir. - '' '' '' '' '' '' '' '' '' '' '' '' 'geçerli bir UTF-8 dizgisi değilse, bu sorun çözülmediğinden,' String.fromCString (up) 'zaten bir çalışma zamanı istisnasıyla başarısız olur. 'Foo()', geçerli bir UTF-8 olmayan bir C dizesini döndüren bir C işlevi olduğu CStringFromUnsafeCChar (foo()) işlevini deneyin. Örneğin: char * foo (void) {statik char buf [] = {-1, 0}; dönüş buf; } –

+0

Eh, drat. Hata rapor zamanı - "CString" ile "UnsafePointer " arasında tek yönlü bir dönüşüm olmamalıdır. –

+1

'reinterpretCast()' mükemmel çalışır, burada uygulayabilirim: http://stackoverflow.com/a/24290234/1187415. Tekrar teşekkürler! –

İlgili konular