ray ray - 8 months ago 40
Swift Question

How to pass an UnsafePointer<UInt8> to a C API by reference?

I wrote some Swift 2.2 code to interact with

C APIs and now I'm trying to convert it to Swift 3.

In Swift 2

let octets = pkcs7_d_data(pkcs7_d_sign(receiptPKCS7).memory.contents)
var ptr = UnsafePointer<UInt8>(octets.memory.data)

// now pass pointer by reference
ASN1_get_object(&ptr, &length, &type, &xclass, end - ptr)

In Swift 3, I've had to make a couple changes

// use guard so i dont have to constantly unwrap these values

guard let octets = pkcs7_d_data(pkcs7_d_sign(receiptPKCS7).pointee.contents),
var ptr = UnsafePointer<UInt8>(octets.pointee.data) else {
return nil

ASN1_get_object(&ptr, &length, &type, &xclass, end - ptr)
// ^^^ this is now a compiler error

Unfortunately, I can no longer pass
by reference, due to this error:

Cannot pass immutable value as inout argument: Implicit conversion from UnsafePointer<UInt8> to UnsafePointer<UInt8>? requires a temporary

and then the rest of the error is cut off (there's no expand arrow).

What I've tried:

  • changing the
    assignment to
    but then I'm told that my existing assignment already produces an optional

  • changed the

What needs to change here?


The problem seems to be that octets.pointee.data is a UnsafeMutablePointer<UInt8>!, but ASN1_get_object expects the address of a UnsafePointer<UInt8>?.

The following code compiles, but I could not test it:

    let octets = pkcs7_d_data(pkcs7_d_sign(receiptPKCS7).pointee.contents),
    let data = octets.pointee.data {

    var ptr: UnsafePointer? = UnsafePointer(data) // (*)
    var length = 0
    var tag: Int32 = 0
    var xclass: Int32 = 0

    ASN1_get_object(&ptr, &length, &tag, &xclass, Int(octets.pointee.length))

(*) is the pointer conversion which makes it compile.