Convert String to int8 array

I have a C struct (old library, blah blah blah) that contains a C string, now I need to convert the CFString and Swift to this c string. Something like

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

      

So I am trying to assign it as

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

      

but the compiler gives me the following error: Cannot convert type (int8, int8, int8 ....) to [CChar].

+3


source to share


1 answer


Possible Solution:

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

      

Inside a block, $0

is a (mutable) pointer to a tuple. This pointer is converted to UnsafeMutablePointer<Int8>

, as expected BSD Library Functionstrlcpy()

.

It also takes advantage of the fact that Swift's string is productName

automatically up to UnsafePointer<UInt8>

as explained in String value for UnsafePointer <UInt8> behavior of function parameters . As mentioned in the comments on this thread, this is done by creating a temporary array UInt8

(or sequence?). This way you can explicitly specify the UTF-8 bytes and put them in the destination:

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

      



Another possible solution (with an intermediate object 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))
}

      


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

      

+6


source







All Articles