当前位置: 首页 > 面试题库 >

如何将自己投射到UnsafeMutablePointer 快速输入

崔恺
2023-03-14
问题内容

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

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

在这里将“自我”转换为UnsafeMutablePointer类型的理想方法是什么?


问题答案:

一个对象的指针(即,实例 引用类型 )可以被转换为一个UnsafePointer<Void>(的夫特映射const void *UnsafeRawPointer在夫特3)和背部。在Objective-C中,您将编写

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

(有关这些转换的确切含义,请参见Clang
ARC文档中的3.2.4桥接转换。)

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

仅在满足Swifts严格类型系统时才需要“复杂”表达式。在编译的代码中,这只是指针之间的强制转换。(***如果您愿意使用“不安全”的方法,可以按照注释中的说明将其写得更短一些,但是编译后的代码是相同的。)

使用此辅助方法,您可以将selfC函数传递为

 let voidPtr = bridge(self)

(或者UnsafeMutablePointer<Void>(bridge(self))如果C函数需要可变的指针),然后将其转换回对象指针(例如在回调函数中),如下所示:

 let mySelf : MyType = bridge(voidPtr)

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

为了完整起见,__bridge_retained__bridge_transferObjective-C 的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()
}

有关“不安全指针”的相关更改,请参见

  • SE-0017更改为非托管以使用UnsafePointer
  • SE-0107 UnsafeRawPointer API


 类似资料:
  • 问题内容: 我有一个映射到Swift的C函数定义为: 我正在尝试传递函数的路径并尝试过: 但是在path [i]上我得到了错误: ‘下标’不可用:不能下标Int范围的字符串 也不 也不管用 除了无法正常工作外,我认为还必须有一种更好,更轻松的方法来做到这一点。以前使用CString在StackOverflow上的答案似乎不再起作用。有什么建议? 问题答案: 使用CString在StackOverf

  • 我的问题不是: < li >维护h2o数据帧的有效方法 < li>H2O运行速度比data.table R慢 < li >在h2o中加载大于内存大小的数据 硬件/空间: 32 个至强线程,带 ~256 GB 内存 要上传约 65 GB 的数据。(约56亿个细胞) 问题: 将数据上传到h2o需要几个小时。这不是任何特殊处理,只是“as.h2o(...)”。 使用“fread”将文本放入空间只需要不到

  • 我刚刚更新到Xcode 6 beta 6,我的代码有以下问题,以前我的代码可以正常工作 提醒子对象的类型为AnyObject?!当我试图将其向下转换为字符串时,它会崩溃,并显示“Swift dynamic cast failure”消息。println打印的值是:可选(嘿,它的测试!) 所以问题是如何正确地投射任何对象?!斯威夫特?

  • 问题内容: 我需要将jzy3d canvas强制转换为java.awt.component,我想使用JCombobox和按钮在框架中显示图表,但是当我要将画布强制转换为component时,程序被删除。谢谢您的回答。我已经尝试过了,对我没有帮助。 Launcher.java: ChartMode.java: 问题答案: 这为我工作。简单的解决方案,当我将jzy3d画布放到画布上并放入面板中时。

  • 共享收货地址接口 wx.openAddress({ success: function (res) { var userName = res.userName; // 收货人姓名 var postalCode = res.postalCode; // 邮编 var provinceName = res.provinceName; // 国标收货地址第一级地址(省)

  • 问题内容: 我正在尝试制作一个增长率()计算器,将结果四舍五入到最接近的整数并从那里重新计算,如下所示: 但到目前为止我一直做不到。 编辑 我有点是这样的: 尽管我不介意它总是四舍五入,但我不喜欢它,因为必须成为变量并在整个程序中进行更改(以便进行下一次计算),我不希望这种情况发生。 问题答案: 库中有一个可用项 (实际上在中 ,但是 在 大多数情况下您需要使用 导入 而不是 直接 使用 ) 。