2014-12-13 3 views
3

У меня есть C struct (старая библиотека, blah blah blah), которая содержит строку C, теперь мне нужно преобразовать строки CFString и Swift в эту строку c. Что-то вродеПреобразование строки в массив int8

struct Product{ 
    char name[50]; 
    char code[20]; 
} 

Так что я пытаюсь присвоить его как

productName.getCString(&myVarOfStructProduct.name, maxLength: 50, encoding: NSUTF8StringEncoding) 

но компилятор дает мне следующую ошибку: не удается преобразовать тип (INT8, INT8, INT8 ....) в [CChar].

+1

Это смешно, потому что у меня была [противоположная проблема] (http://stackoverflow.com/questions/27455773/converting-a-c-char-array-to-a-string). – zneak

ответ

6

Возможное решение:

withUnsafeMutablePointer(&myVarOfStructProduct.name) { 
    strlcpy(UnsafeMutablePointer($0), productName, UInt(sizeofValue(myVarOfStructProduct.name))) 
} 

Внутри блока, $0 является (изменяемый) указатель на кортеж. Этот указатель преобразован в UnsafeMutablePointer<Int8>, как ожидалось, BSD library function strlcpy().

Он также использует тот факт, что Swift строка productName является автоматически к UnsafePointer<UInt8> , как описано в String value to UnsafePointer<UInt8> function parameter behavior. Как упоминалось в комментариях в этом потоке , это делается путем создания временного массива UInt8 (или последовательности?). Так альтернативно можно перечислить UTF-8 байт в явном виде и поместить их в пункт назначения:

withUnsafeMutablePointer(&myVarOfStructProduct.name) { 
    tuplePtr -> Void in 
    var uint8Ptr = UnsafeMutablePointer<UInt8>(tuplePtr) 
    let size = sizeofValue(myVarOfStructProduct.name) 
    var idx = 0 
    if size == 0 { return } // C array has zero length. 
    for u in productName.utf8 { 
     if idx == size - 1 { break } 
     uint8Ptr[idx++] = u 
    } 
    uint8Ptr[idx] = 0 // NUL-terminate the C string in the array. 
} 

Еще одно возможное решение (с промежуточным NSData объекта):

withUnsafeMutablePointer(&myVarOfStructProduct.name) { 
    tuplePtr -> Void in 
    let tmp = productName + String(UnicodeScalar(0)) // Add NUL-termination 
    let data = tmp.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)! 
    data.getBytes(tuplePtr, length: sizeofValue(myVarOfStructProduct.name)) 
} 

Обновление для Swift 3:

withUnsafeMutablePointer(to: &myVarOfStructProduct.name) { 
    $0.withMemoryRebound(to: Int8.self, capacity: MemoryLayout.size(ofValue: myVarOfStructProduct.name)) { 
     _ = strlcpy($0, productName, MemoryLayout.size(ofValue: myVarOfStructProduct.name)) 
    } 
} 
Смежные вопросы