How to get an UnsafeMultablePointer<mach_port_t> to pass to IOMasterPort?

Ok, continuing with converting my app to Swift...


I need to call IOMasterPort but I cannot figure out exactly how to set up the call. I have this working fine in my Obj-C code BTW.


The docs. give the definition:


func IOMasterPort(_

bootstrapPort
: mach_port_t, _
masterPort
: UnsafeMutablePointer<mach_port_t>) -> kern_return_t


and say that you can pass MACH_PORT_NULL as the default for the bootstrapPort. This is potentially an issue since the compiler is identifying MACH_PORT_NULL as a UInt32 whereas the function definition calls for a mach_port_t. That may not be an actual problem, since I cannot figure out how to pass the second parameter which is specified as:


UnsafeMutablePointer<mach_port_t>


so I tried:


var mPort: mach_port_t = kIOMasterPortDefault

var mPortP: UnsafeMutablePointer<mach_port_t>

mPortP = &mPort


but I get the compiler error:


'inout mach_port_t' is not convertible to 'UnsafeMutablePointer<mach_port_t>'


Anyone know how I can get an UnsafeMutablePointer to a mach_port_t?

Accepted Answer

In most use cases, when you need to pass a UnsafeMutablePointer<T> to a C-function, you declare a variable of type T (not UnsafeMutablePointer<T>), and pass it as an inout paramter (prefix `&`).

    let bootstrapPort: mach_port_t = mach_port_t(MACH_PORT_NULL)
    var masterPort: mach_port_t = mach_port_t()
    let result = IOMasterPort(bootstrapPort, &masterPort)


I haven't tried IOKit in Swift yet, but you need to remember that not all features of C-language APIs are imported into Swift.

Such as C-unions, complex macros or functions with variable length arguments are not available in Swift.

Thanks OOPer - that's exactly what I needed. I had actually tried


var masterPort: mach_port_t = mach_port_t()

let result = IOMasterPort(MACH_PORT_NULL, &masterPort)


which doesn't compile so the real problem was that I didn't initialise a mach_port_t with MACH_PORT_NULL but instead just passed MACH_PORT_NULL which is of course a UInt32 rather than a mach_port_t. I was misled by the docs a bit here I think.

One bad thing is the error message that current Swift generates:

error: cannot invoke 'IOMasterPort' with an argument list of type '(Int32, inout mach_port_t)'


If the message was 'Int32 cannot be convertible to UInt32', or something like that, you'd be getting the right answer yourself far sooner.


Chris Lattner says, that sorts of things are much improved in the coming beta, and I really expect that.


ADDITION:

I found the note following the error message:

note: expected an argument list of type '(mach_port_t, UnsafeMutablePointer<mach_port_t>)'


This is itself a fine improvement comparing to the older versions. One step ahead please.

I never noticed that note until you pointed it out! Like you I look forward to significantly improved error reporting.

While it's interesting to see all of this

IOMasterPort
info fly by, the simplest option by far is to avoid that call and simply using the
kIOMasterPortDefault
global variable.

The following compiles in both Xcode 7b4 and Xcode 6.4:

import IOKit

IOServiceGetMatchingService(kIOMasterPortDefault, nil)

Just by way of history,

kIOMasterPortDefault
wasn't part of the original Mac OS X 10.10 API, so lots of folks wrote lots of code using
IOMasterPort
. These days that's not necessary;
kIOMasterPortDefault
was introduced a long time ago (I checked the Mac OS X 10.2 SDK, and it has it), so there's really no need to call
IOMasterPort
.

Of course, the information in this thread will be handy when calling other I/O Kit APIs.

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
How to get an UnsafeMultablePointer&lt;mach_port_t&gt; to pass to IOMasterPort?
 
 
Q