Cast a Swift struct to UnsafeMutablePointer<Void>

10,328

Solution 1

As far as I know, the shortest way is:

var myStruct = TheStruct()
var address = withUnsafeMutablePointer(&myStruct) {UnsafeMutablePointer<Void>($0)}

But, why you need this? If you want pass it as a parameter, you can (and should):

func foo(arg:UnsafeMutablePointer<Void>) {
    //...
}

var myStruct = TheStruct()
foo(&myStruct)

Solution 2

Most of the method prototypes have been changed as Swift evolved over the years. Here is the syntax for Swift 5:

var struct = TheStruct()

var unsafeMutablePtrToStruct = withUnsafeMutablePointer(to: &struct) {
    $0.withMemoryRebound(to: TheStruct.self, capacity: 1) {
        (unsafePointer: UnsafeMutablePointer<TheStruct>) in

        unsafePointer
    }
}
Share:
10,328

Related videos on Youtube

popisar
Author by

popisar

Updated on June 04, 2022

Comments

  • popisar
    popisar almost 2 years

    Is there a way to cast a Swift struct's address to a void UnsafeMutablePointer?
    I tried this without success:

    struct TheStruct {
        var a:Int = 0
    }
    
    var myStruct = TheStruct()
    var address = UnsafeMutablePointer<Void>(&myStruct)
    

    Thanks!

    EDIT: the context
    I am actually trying to port to Swift the first example in Learning CoreAudio.
    This is what I have done until now:

    func myAQInputCallback(inUserData:UnsafeMutablePointer<Void>,
        inQueue:AudioQueueRef,
        inBuffer:AudioQueueBufferRef,
        inStartTime:UnsafePointer<AudioTimeStamp>,
        inNumPackets:UInt32,
        inPacketDesc:UnsafePointer<AudioStreamPacketDescription>)
     { }
    
    struct MyRecorder {
        var recordFile:     AudioFileID = AudioFileID()
        var recordPacket:   Int64       = 0
        var running:        Boolean     = 0
    }
    
    var queue:AudioQueueRef = AudioQueueRef()
    AudioQueueNewInput(&asbd,
        myAQInputCallback,
        &recorder,  // <- this is where I *think* a void pointer is demanded
        nil,
        nil,
        UInt32(0),
        &queue)
    

    I am doing efforts to stay in Swift, but if this turns out to be more a problem than an advantage, I will end up linking to a C function.

    EDIT: bottome line
    If you came to this question because you are trying to use a CoreAudio's AudioQueue in Swift... don't. (read the comments for details)

    • popisar
      popisar about 9 years
      Thanks rintaro. If it's true, then I am wasting my time... Why then is there this definition in the Apple's doc? SWIFT typealias AudioQueueInputCallback = CFunctionPointer<((UnsafeMutablePointer<Void>, AudioQueueRef, AudioQueueBufferRef, UnsafePointer<AudioTimeStamp>, UInt32, UnsafePointer<AudioStreamPacketDescription>) -> Void)> This lead me to think that, if you define a regular function with the demanded signature, it would be possible to pass it to the AudioQueueNewInput as an AudioQueueInputCallback.
    • popisar
      popisar about 9 years
      And the last lines in the link pointed out by Martin are maybe the most useful to my problem: "It's an incredibly painful workaround for a problem that you shouldn't be trying to express in Swift. Code that must manipulate pointers, especially function pointers, is best left in a C or Objective-C file. Otherwise, you're just fighting an unnecessary battle against the language -especially because it has such great support for C and Objective-C interoperability." Thanks everyone!
  • Martin R
    Martin R about 9 years
    The first variant is really unsafe because the pointer might be used beyond the lifetime of myStruct. – If the pointer is needed as an argument to a C function then withUnsafeMutablePointer(&myStruct) { someCFunction(UnsafeMutablePointer<Void>($0)) } is also an option.
  • rintaro
    rintaro about 9 years
    We can pass UnsafeMutablePointer<TheStruct> as UnsafeMutablePointer<Void>. So withUnsafeMutablePointer(&myStruct) { someCFunction($0) } also works.
  • Kirsteins
    Kirsteins about 9 years
    @MartinR That why it has "unsafe" in the type name :)
  • Martin R
    Martin R about 9 years
    @Kirsteins: Yes, but there is (in my opinion) still a difference between using the pointer inside the closure, and passing it to the outside.