将String转换为int8数组

时间:2014-12-13 17:55:23

标签: string swift

我有一个包含C字符串的C结构(旧库,blah blah blah),现在我需要将CFString和Swift字符串转换为此c字符串。像

这样的东西
struct Product{
   char name[50];
   char code[20];
}

所以我试图将其指定为

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

但编译器给出了以下错误:无法将类型(int8,int8,int8 ....)转换为[CChar]。

1 个答案:

答案 0 :(得分:8)

可能的解决方案:

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))
    }
}