如何将自己转换为 UnsafeMutablePointer<Void> 输入 swift

How to cast self to UnsafeMutablePointer<Void> type in swift

在调用以下代码时尝试将 "self" 传递给 swift 中的 C 函数:

var callbackStruct : AURenderCallbackStruct = 
    AURenderCallbackStruct.init(
      inputProc: recordingCallback,
      inputProcRefCon: UnsafeMutablePointer<Void>
    )

在这里将 "self" 转换为 UnsafeMutablePointer 类型的理想方法是什么?

在我看来,这就是 withUnsafeMutablePointer 的用途 - 将任意 Swift 指针转换为 C 指针。所以大概你可以这样做(我没有尝试过,但我测试过的代码可以安全运行):

var mself = self 
withUnsafeMutablePointer(&mself) { v in
    let v2 = UnsafeMutablePointer<Void>(v)
    myStruct.inputProcRefCon = v2
}

这个答案看起来不像 Martin R's answer 那样针对特定主题的回调,但可能有用...

您通常可以使用 & 运算符将任何类型的值传递给不安全的 void 指针:

func baz(p: UnsafeMutablePointer<Void>) -> String {
    return "\(p)"
}

var num = 5
print(baz(&num))

但是,要传递 self,您需要在 self 可变的上下文中这样做。这意味着您需要在值类型的变异方法(或 init)中执行此操作,而不是引用类型:

struct FooValue {
    mutating func bar() {
        print(baz(&self))
    }
}

var myFooValue = FooValue()
myFooValue.bar()

如果您想使用引用类型,您需要创建引用的本地副本并将指针传递给它:

class FooReference {
    func bar() {
        var localSelf = self
        print(baz(&localSelf))
    }
}

let myFooReference = FooReference()
myFooReference.bar()

对象指针(即引用类型的实例)可以是 转换为 UnsafePointer<Void>(Swift 3 中 const void *UnsafeRawPointer 的 Swift 映射)并返回。在 Objective-C 你会写

void *voidPtr = (__bridge void*)self;
// 
MyType *mySelf = (__bridge MyType *)voidPtr;

(请参阅 Clang ARC 文档中的 3.2.4 Bridged casts,了解这些的准确含义 演员表。)

Swift 有一个 Unmanaged 类型用于此目的。 使用起来有点麻烦,因为它适用于 COpaquePointer 而不是 UnsafePointer<Void>。这里有两个辅助方法 (以 Objective-C __bridge 演员命名):

func bridge<T : AnyObject>(obj : T) -> UnsafePointer<Void> {
    return UnsafePointer(Unmanaged.passUnretained(obj).toOpaque())
    // return unsafeAddressOf(obj) // ***
}

func bridge<T : AnyObject>(ptr : UnsafePointer<Void>) -> T {
    return Unmanaged<T>.fromOpaque(COpaquePointer(ptr)).takeUnretainedValue()
    // return unsafeBitCast(ptr, T.self) // ***
}

"complicated"表达式只需要满足Swifts 严格的类型系统。在编译后的代码中,这只是一个演员 指针之间。 (可以写得更短,如 *** 评论中所示 如果你愿意使用"unsafe"方法,但编译 代码相同。)

使用此辅助方法,您可以将 self 传递给 C 函数,如

 let voidPtr = bridge(self)

(或 UnsafeMutablePointer<Void>(bridge(self)) 如果 C 函数需要 可变指针),并将其转换回对象指针——例如 在回调函数中 – as

 let mySelf : MyType = bridge(voidPtr)

不会发生所有权转移,因此您必须确保 self 只要使用 void 指针就存在。


为了完整起见,Objective-C 中 __bridge_retained__bridge_transfer 的 Swift 等效为

func bridgeRetained<T : AnyObject>(obj : T) -> UnsafePointer<Void> {
    return UnsafePointer(Unmanaged.passRetained(obj).toOpaque())
}

func bridgeTransfer<T : AnyObject>(ptr : UnsafePointer<Void>) -> T {
    return Unmanaged<T>.fromOpaque(COpaquePointer(ptr)).takeRetainedValue()
}

bridgeRetained() 将对象指针转换为 void 指针并 保留对象。 bridgeTransfer() 转换 返回对象指针的 void 指针并消耗保留。

一个优点是对象不能在 调用,因为持有一个强引用。缺点是 呼叫必须适当平衡,并且很容易导致保留 周期。


更新 Swift 3 (Xcode 8):

func bridge<T : AnyObject>(obj : T) -> UnsafeRawPointer {
    return UnsafeRawPointer(Unmanaged.passUnretained(obj).toOpaque())
}

func bridge<T : AnyObject>(ptr : UnsafeRawPointer) -> T {
    return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
}

func bridgeRetained<T : AnyObject>(obj : T) -> UnsafeRawPointer {
    return UnsafeRawPointer(Unmanaged.passRetained(obj).toOpaque())
}

func bridgeTransfer<T : AnyObject>(ptr : UnsafeRawPointer) -> T {
    return Unmanaged<T>.fromOpaque(ptr).takeRetainedValue()
}

对 "unsafe pointers" 的相关更改在

中进行了描述
func bridge<T : AnyObject>(obj : T) -> UnsafePointer<Void> {
return UnsafePointer(Unmanaged.passUnretained(obj).toOpaque())
}


func bridge<T : AnyObject>(ptr : UnsafePointer<Void>) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
}

func bridgeRetained<T : AnyObject>(obj : T) -> UnsafePointer<Void> {
return UnsafePointer( Unmanaged.passRetained(obj).toOpaque())}

func bridgeTransfer<T : AnyObject>(ptr : UnsafePointer<Void>) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeRetainedValue()}