2016-07-17 12 views
6

W Swift 3 funkcja C z podpisem const char *f() jest mapowana na UnsafePointer<Int8>! f() podczas importowania. Jest to wynik może być przekształcony w ciąg Swift jako:Konwertowanie tablic łańcuchów C na ciąg znaków Swift

let swiftString = String(cString: f()) 

Pytanie brzmi, jak NULL zakończone C tablica łańcuchów C mogą być odwzorowywane Swift tablicy ciągów?

Oryginalny C podpis:

const char **f() 

importowane Swift podpis:

UnsafeMutablePointer<UnsafePointer<Int8>?>! f() 

Swift tablicę ciągów:

let stringArray: [String] = ??? 

Odpowiedz

9

Nie ma wbudowanej metody, o ile mi wiedzieć. trzeba iteracyjne nad zwróconej tablicy wskaźnika, konwersji ciągów C do Swift String s, aż nil wskaźnik znajduje się:

if var ptr = f() { 
    var strings: [String] = [] 
    while let s = ptr.pointee { 
     strings.append(String(cString: s)) 
     ptr += 1 
    } 
    // Now p.pointee == nil. 

    print(strings) 
} 

Uwagi: Swift 3 wykorzystuje opcjonalne wskaźniki do wskaźników, które mogą być nil. W twoim przypadku, f() zwraca nieopakowane opcje opcjonalne, ponieważ plik nagłówka nie jest "skontrolowany": Kompilator nie wie, czy funkcja może zwrócić wartość NULL, czy też nie.

Używanie „adnotacje wartości null” można podać tę informację do Swift kompilatora:

const char * _Nullable * _Nullable f(void); 
// Imported to Swift as 
public func f() -> UnsafeMutablePointer<UnsafePointer<Int8>?>? 

jeśli funkcja może powrócić NULL i

const char * _Nullable * _Nonnull f(void); 
// Imported to Swift as 
public func f() -> UnsafeMutablePointer<UnsafePointer<Int8>?> 

jeśli f() gwarantuje zwróci wynik inny niż NULL.

Aby uzyskać więcej informacji na temat adnotacji znojności, zobacz na przykład Nullability and Objective-C na blogu Swift.

+0

... i bardzo podobne techniki są potrzebne w innych językach (w tym w C++), które obsługują "prawdziwy" typ "String". Każdy z tych "innych" języków zachowuje oddzielną "długość" dla każdej wartości łańcucha: nie polega na kończeniu pustych bajtów. Ale wszystkie mają metody, które są specjalnie zaprojektowane, aby sobie z nimi poradzić. (I zwykle zawierają bajt NULL na końcu aktualnej wartości, którą przechowują.) –

+0

... i ... * "meh" ... jeśli chodzi o komputery cyfrowe, to "nigdy nie mów" nigdy "." Jeśli jest to wskaźnik, może to być "NULL". Każdy przyszły * błąd * w 'f()', który wytworzył tę wartość zwracającą rozwinie się w * bardzo * nieprzyjemny i trudny do zlokalizowania błąd, marnując może godziny z tego, co miało golić mikrosekundy. Jestem bardzo * konserwatywnym * programistą ... –

+0

@MikeRobinson: Nie dodałem tej uwagi do "golenia mikrosekund", ale do zwrócenia uwagi na adnotacje nullability. Oczywiście można omówić, czy zwracana wartość API, która jest * udokumentowana * w celu zwrócenia poprawnego wskaźnika, powinna być sprawdzana przy każdym wywołaniu, lub jeśli jest to uważane za błąd programistyczny i powinno nastąpić wcześniej. –