Cannot convert value of UnsafeMutableRawPointer to BluetoothDeviceAddress

Viewed 1089

I'm trying to convert this source code :

BluetoothDeviceAddress *deviceAddress = malloc(sizeof(BluetoothDeviceAddress));

to Swift, which gives me :

let deviceAddress: BluetoothDeviceAddress = malloc(sizeof(BluetoothDeviceAddress))

But, I found that in Swift 3/4, sizeof is not used anymore but this is not my error, Xcode returns :

"Cannot convert value of type 'UnsafeMutableRawPointer!' to specified type 'BluetoothDeviceAddress'"

I tried changing to malloc(MemoryLayout<BluetoothDeviceAddress>.size) but still the same error.

EDIT: As proposed in the comments by MartinR, I tried changing to let deviceAddress = BluetoothDeviceAddress() but then when I want to initialize an IOBluetoothDevice, I still get an error (selectedDevice is a var for IOBluetoothDevice):

self.selectedDevice = IOBluetoothDevice(address: deviceAddress)

Error : Cannot convert value of type 'BluetoothDeviceAddress' to expected argument type 'UnsafePointer!'

Best,

Antoine

1 Answers

To answer your direct question: Acquiring a typed pointer from a raw pointer is called "binding" in Swift and done with bindMemory():

let ptr = malloc(MemoryLayout<BluetoothDeviceAddress>.size)! // Assuming that the allocation does not fail
let deviceAddressPtr = ptr.bindMemory(to: BluetoothDeviceAddress.self, capacity: 1)
deviceAddressPtr.initialize(to: BluetoothDeviceAddress())
// Use deviceAddressPtr.pointee to access pointed-to memory ...

let selectedDevice = IOBluetoothDevice(address: deviceAddressPtr)
// ...

deviceAddressPtr.deinitialize(count: 1)
free(ptr)

Instead of malloc/free, one would use the allocate/release methods of Unsafe(Mutable)Pointer in Swift:

let deviceAddressPtr = UnsafeMutablePointer<BluetoothDeviceAddress>.allocate(capacity: 1)
deviceAddressPtr.initialize(to: BluetoothDeviceAddress())
// Use deviceAddressPtr.pointee to access pointed-to memory ...

let selectedDevice = IOBluetoothDevice(address: deviceAddressPtr)
// ...

deviceAddressPtr.deinitialize(count: 1)
deviceAddressPtr.deallocate(capacity: 1)

See SE-0107 UnsafeRawPointer API for more information about raw pointers and binding.

However, it is usually easier to create a value of that type directly and pass that as inout expression with &. Example:

var deviceAddress = BluetoothDeviceAddress()
// ...

let selectedDevice = IOBluetoothDevice(address: &deviceAddress)
// ...
Related