[swift-users] Updating C-wrapper to Swift 3

John Brownie john_brownie at sil.org
Wed Sep 28 01:29:16 CDT 2016

I have a Swift wrapper for the expat XML parser, and I just went through 
the update to Swift 3, and I'm thrown a series of errors that mostly 
appear to be of two types. Here is a representative function of the 
first type:

     func parse() throws {
         var done = false
         while !done {
             let buffer: UnsafeMutablePointer<Void> = 
XML_GetBuffer(parser, Int32(bufsize))
             if buffer == nil {
                 let errorCode = XML_GetErrorCode(parser)
                 throw ExpatError(reason: "Error \(errorCode), 
             let bytesRead = 
readData(UnsafeMutablePointer<UInt8>(buffer), bufferLength: bufsize)
             done = bytesRead < bufsize
             if XML_ParseBuffer(parser, Int32(bytesRead), Int32(done ? 1 
: 0)) != XML_STATUS_OK {
                 let errorCode = XML_GetErrorCode(parser)
                 throw ExpatError(reason: "Error \(errorCode), 

Xcode 8's migrator changed the declaration of buffer to 
UnsafeMutableRawPointer?, but the readData call gives an error:

Cannot invoke initializer for type 'UnsafeMutablePointer<UInt8>' with an 
argument list of type '(UnsafeMutableRawPointer?)'
Pointer conversion restricted: use '.assumingMemoryBound(to:)' or 
'.bindMemory(to:capacity:)' to view memory as a type.
Overloads for 'UnsafeMutablePointer<UInt8>' exist with these partially 
matching parameter lists: (RawPointer), (OpaquePointer), 
(OpaquePointer?), (UnsafeMutablePointer<Pointee>), 

Where can I read up on how to make the conversion? My initial effort is:

             let bytesRead = readData(buffer!.bindMemory(to: UInt8.self, 
capacity: bufsize), bufferLength: bufsize)

That's more or less thrashing around with no real understanding.

The second type is turning a closure into the appropriate C function 
pointer. For example:

             XML_SetEndElementHandler(parser) { (userData: 
UnsafeMutableRawPointer, name: UnsafePointer<XML_Char>) -> Void in
                 let theParser = unsafeBitCast(userData, to: 
                 let theName = ExpatSwift.getString(name)

This gets an error:

Cannot convert value of type '(UnsafeMutableRawPointer, 
UnsafePointer<XML_Char>) -> Void' to expected argument type 

XML_EndElementHandler is defined as:

typedef void (XMLCALL *XML_EndElementHandler) (void *userData,
                                                const XML_Char *name);

Here I have no real clue as to how to fix it.

So, any pointers to either how to fix these problems or to a good source 
to read to understand them?

John Brownie
In Finland on furlough from SIL Papua New Guinea

More information about the swift-users mailing list