Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issues using withMemoryRebound in Swift 3

I have an app that was previously using UnsafeMutablePointer to call C-functions like so:

    var size     = HOST_BASIC_INFO_COUNT
    let hostInfo = host_basic_info_t.allocate(capacity: 1)
    let result = host_info(machHost, HOST_BASIC_INFO,
                                     UnsafeMutablePointer(hostInfo), &size)

Since moving to Swift 3, Xcode Beta 6 you are prompted to use withMemoryRebound. Problem is I don't understand how to use it in this situation, and there is no documentation or sample code for it yet. My approach:

    var size     = HOST_BASIC_INFO_COUNT
    let hostInfo = host_basic_info_t.allocate(capacity: 1)
    let temp = hostInfo.withMemoryRebound(to: host_info_t!.self, capacity: Int(size)) {
        UnsafeBufferPointer(start: $0, count: Int(size))
    }
    let result = host_statistics(machHost,
                                 HOST_BASIC_INFO,
                                 temp.baseAddress?.pointee,
                                 &size)

Simply crashes with Bad Access. What is the correct way to use withMemoryRebound?

like image 420
Oskar Avatar asked Aug 17 '16 11:08

Oskar


3 Answers

hostInfo is a UnsafeMutablePointer<host_basic_info>, and that pointer must be "rebound" to a pointer to HOST_BASIC_INFO_COUNT items of integer_t, as expected by the hostInfo() function:

let HOST_BASIC_INFO_COUNT = MemoryLayout<host_basic_info>.stride/MemoryLayout<integer_t>.stride
var size = mach_msg_type_number_t(HOST_BASIC_INFO_COUNT)
let hostInfo = host_basic_info_t.allocate(capacity: 1)
let result = hostInfo.withMemoryRebound(to: integer_t.self, capacity: HOST_BASIC_INFO_COUNT) {
    host_info(mach_host_self(), HOST_BASIC_INFO, $0, &size)
}

print(result, hostInfo.pointee)
hostInfo.deallocate(capacity: 1)

Instead of allocate/deallocate you can also work with a local variable and pass its address:

let HOST_BASIC_INFO_COUNT = MemoryLayout<host_basic_info>.stride/MemoryLayout<integer_t>.stride
var size = mach_msg_type_number_t(HOST_BASIC_INFO_COUNT)
var hostInfo = host_basic_info()

let result = withUnsafeMutablePointer(to: &hostInfo) {
    $0.withMemoryRebound(to: integer_t.self, capacity: Int(size)) {
        host_info(mach_host_self(), Int32(HOST_BASIC_INFO), $0, &size)
    }
}
print(result, hostInfo)
like image 176
Martin R Avatar answered Oct 23 '22 05:10

Martin R


this one should work better with swift 3

result = withUnsafePointer(to: &size) {
            $0.withMemoryRebound(to: integer_t.self, capacity: HOST_BASIC_INFO_COUNT) {
                host_info(machHost, HOST_BASIC_INFO,
                          $0,
                          &size)
            }
like image 39
Hicham Bagui Avatar answered Oct 23 '22 05:10

Hicham Bagui


withMemoryRebound is very similar to withUnsafePointer function.

capacity need to be size of host_info_t.

You need to do like below :

let temp = hostInfo.withMemoryRebound(to: host_info_t.self or type(of: host_info), capacity: MemoryLayout<host_info_t>.stride * Int(size))

additionally, you don't need UnsafeBufferPointer.

like image 26
oozoofrog Avatar answered Oct 23 '22 06:10

oozoofrog