14

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
  • 379
  • 2
  • 3
  • 15
  • Can you add some information *why* the address is needed as a void pointer? – Martin R Apr 10 '15 at 09:35
  • Sure! I am trying to use CoreAudio in Swift. The compiler complains that the arguments passed to AudioQueueNewInput are not what they should be, and the struct passed seems to be the cause of that. – popisar Apr 10 '15 at 10:13
  • You should add more information and code to the question. Which function exactly, how do you try to call it, the exact error message ... – Martin R Apr 10 '15 at 10:14
  • I think `AudioQueueNewInput` is not usable in *pure* Swift. You cannot *create* `AudioQueueInputCallback` instance in Swift. – rintaro Apr 10 '15 at 10:20
  • 1
    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, AudioQueueRef, AudioQueueBufferRef, UnsafePointer, UInt32, UnsafePointer) -> 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 Apr 10 '15 at 10:31
  • Sad to say, you can *receive* `CFunctionPointer` from Obj-C code but cannot *create* it. – rintaro Apr 10 '15 at 10:33
  • Compare http://stackoverflow.com/questions/25341632/pass-c-function-callback-in-swift. – Martin R Apr 10 '15 at 10:35
  • Type `CFunctionPointer` in Xcode and command+click shows: "Though not directly useful in Swift, `CFunctionPointer` can be used to safely pass a C function pointer, received from one C or Objective-C API, to another C or Objective-C API." – rintaro Apr 10 '15 at 10:37
  • I missed the "Though not directly useful in Swift"... :-) – popisar Apr 10 '15 at 10:40
  • 2
    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! – popisar Apr 10 '15 at 10:41
  • @popisar thanks for great advice not to implement it with swift – tatiana_c Mar 30 '17 at 13:40

2 Answers2

19

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)
rintaro
  • 51,423
  • 14
  • 131
  • 139
  • 3
    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($0)) }` is also an option. – Martin R Apr 10 '15 at 09:41
  • We can pass `UnsafeMutablePointer` as `UnsafeMutablePointer`. So `withUnsafeMutablePointer(&myStruct) { someCFunction($0) }` also works. – rintaro Apr 10 '15 at 09:46
  • 1
    @MartinR That why it has "unsafe" in the type name :) – Kirsteins Apr 10 '15 at 09:47
  • 1
    @Kirsteins: Yes, but there is (in my opinion) still a difference between using the pointer inside the closure, and passing it to the outside. – Martin R Apr 10 '15 at 09:50
1

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
    }
}
Aamir
  • 16,329
  • 10
  • 59
  • 65