swift - 如何快速将自己转换为 UnsafeMutablePointer<Void> 类型

标签 swift pointers casting unsafe-pointers

在调用以下代码时,试图在 swift 中将“self”传递给 C 函数:

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

在此处将“self”转换为 UnsafeMutablePointer 类型的理想方法是什么?

最佳答案

对象指针(即引用类型的实例)可以是 转换为 UnsafePointer<Void> (const void * 的 Swift 映射,UnsafeRawPointer 在 Swift 3 中)并返回。在 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 cas​​t 命名):

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) // ***
}

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

使用此辅助方法,您可以传递 self到 C 函数作为

 let voidPtr = bridge(self)

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

 let mySelf : MyType = bridge(voidPtr)

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


为了完整起见,Swift 相当于 __bridge_retained__bridge_transfer来自 Objective-C 的是

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()
}

“不安全指针”的相关变化在

关于swift - 如何快速将自己转换为 UnsafeMutablePointer<Void> 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33294620/

相关文章:

cJSON内存泄漏

从不同大小的整数转换为指针 [-Wint-to-pointer-cast]

Java泛型,在方法调用期间定义类型

ios - 无法使用分段控件显示 UICollectionView

ios - 在其他 ViewControllers Swift 中访问变量

swift - 如何在 Xcode 7 上使用 swift 代码使按钮不可见?

ios - UICollectionView 中标题 View 的高度

c - 链表循环迭代改变全局变量头

c++ - 返回空指针

generics - 未经检查的通用类类型IDE警告的转换