cswiftswift2unsafe-pointerssecure-transport

copy NSData to UnsafeMutablePointer<Void>


Hi there stackoverflowers. I'm implementing a wrapper for Secure Transport and I'm stuck on some of the C -> Swift syntax.

func sslReadCallback(connection: SSLConnectionRef,
    data: UnsafeMutablePointer<Void>,
    var dataLength: UnsafeMutablePointer<Int>) -> OSStatus
{
    //let bytesRequested = dataLength.memory
    let transportWrapper:SecureTransportWrapper = UnsafePointer(connection).memory
    let bytesRead:NSData = transportWrapper.readFromConnectionFunc(transportWrapper.connection)
    
    dataLength = UnsafeMutablePointer<Int>.alloc(1)
    dataLength.initialize(bytesRead.length)
    
    if (bytesRead.length == 0)
    {
        return OSStatus(errSSLClosedGraceful)
    }
    else
    {
        data.alloc(sizeof(bytesRead.length)) //<----compile error here
        return noErr
    }
}

I've marked the location of the compile error. I don't blame it for erring, I was kind of guessing here :P. I'm trying to copy the the NSData to the data:UnsafeMutablePointer. How do I do that?

Compile error:

/Users/*/SecureTransportWrapper.swift:108:9: Static member 'alloc' cannot be used on instance of type 'UnsafeMutablePointer' (aka 'UnsafeMutablePointer<()>')

Thanks a ton!

================

Update: here is the api doc for what the sslReadCallback is supposed to do:

connection: A connection reference.

data: On return, your callback should overwrite the memory at this location with the data read from the connection.

dataLength: On input, a pointer to an integer representing the length of the data in bytes. On return, your callback should overwrite that integer with the number of bytes actually transferred.

Excerpt from here


Solution

  • OK, lets go through your code:

    dataLength = UnsafeMutablePointer<Int>.alloc(1)
    dataLength.initialize(bytesRead.length)
    

    dataLength is a pointer you get passed in, it is where the caller of the function both gives you the size of the buffer and wants you to put the number of bytes you read. You don't need to alloc this, it is already allocated.

    (Irrelevant for this example but: Also in alloc(N) and initialize(N) the N should be the same (it is the amount of memory being allocated, and then initialized))

    I think what you want (Swift 3 uses pointee instead of memory) is this:

    dataLength.memory = bytesRead.length
    

    The C API says that you also get the size of the data buffer from this variable. data will be pre-allocated for this size.

    Make sure the data you read fits (bytesRead.length <= dataLength.memory), then just do a

    memcpy(data, bytesRead.bytes, bytesRead.length)
    

    That's all.