Cyan Lee
Cyan Lee

Reputation: 341

Converting a String to UnsafeMutablePointer<UInt16>

I'm trying to use a library which was written in C. I've imported .a and .h files at Xcode project, and checked it works properly. I've already made them working on Objective-C, and now for Swift.

A problem I've got is functions' arguments. There's a function requires an argument widechar(defined as typedef Unsigned short int in Library), which was UnsafeMutablePointer<UInt16> in Swift. The function translates it and return the result.

So I should convert a String to UnsafeMutablePointer<UInt16>. I tried to find the right way to converting it, but I've only got converting it to UnsafeMutablePointer<UInt8>. I couldn't find answer/information about converting String to UnsafeMutablePointer<UInt16>.

Here's a source code I've written.

extension String{
    var utf8CString: UnsafePointer<Int8> {
        return UnsafePointer((self as NSString).utf8String!)
    }
}

func translate(toBraille: String, withTable: String) -> [String]? {
    let filteredString = toBraille.onlyAlphabet

    let table = withTable.utf8CString

    var inputLength = CInt(filteredString.count)
    var outputLength = CInt(maxBufferSize)
    let inputValue = UnsafeMutablePointer<widechar>.allocate(capacity: Int(outputLength))
    let outputValue = UnsafeMutablePointer<widechar>.allocate(capacity: Int(outputLength))

    lou_translateString(table, inputValue, &inputLength, outputValue, &outputLength, nil, nil, 0)
    //This is a function that I should use. 

    let result:[String] = []

    return result
}

Upvotes: 1

Views: 429

Answers (1)

Martin R
Martin R

Reputation: 539685

You have to create an array with the UTF-16 representation of the Swift string that you can pass to the function, and on return create a Swift string from the UTF-16 array result.

Lets assume for simplicity that the C function is imported to Swift as

func translateString(_ source: UnsafeMutablePointer<UInt16>, _ sourceLen: UnsafeMutablePointer<CInt>,
               _ dest: UnsafeMutablePointer<UInt16>, _ destLen: UnsafeMutablePointer<CInt>) 

Then the following should work (explanations inline):

// Create array with UTF-16 representation of source string:
let sourceString = "Hello world"
var sourceUTF16 = Array(sourceString.utf16)
var sourceLength = CInt(sourceUTF16.count)

// Allocate array for UTF-16 representation of destination string:
let maxBufferSize = 1000
var destUTF16 = Array<UInt16>(repeating: 0, count: maxBufferSize)
var destLength = CInt(destUTF16.count)

// Call translation function:
translateString(&sourceUTF16, &sourceLength, &destUTF16, &destLength)

// Create Swift string from UTF-16 representation in destination buffer:
let destString = String(utf16CodeUnits: destUTF16, count: Int(destLength))

I have assumed that the C function updates destLength to reflect the actual length of the translated string on return.

Upvotes: 2

Related Questions