简体   繁体   English

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

[英]How to cast self to UnsafeMutablePointer<Void> type in swift

Trying to pass "self" to a C function in swift, when calling following code: 调用以下代码时,试图将“ self”快速传递给C函数:

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

What is the ideal way to cast "self" to a UnsafeMutablePointer type here? 在这里将“自我”转换为UnsafeMutablePointer类型的理想方法是什么?

An object pointer (ie an instance of a reference type ) can be converted to a UnsafePointer<Void> (the Swift mapping of const void * , UnsafeRawPointer in Swift 3) and back. 可以将对象指针(即引用类型的实例)转换为UnsafePointer<Void> (在Swift 3中为const void *的Swift映射,在UnsafeRawPointer中是)。 In Objective-C you would write 在Objective-C中,您将编写

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

(See 3.2.4 Bridged casts in the Clang ARC documentation for the precise meaning of these casts.) (有关这些转换的确切含义,请参见Clang ARC文档中的3.2.4桥接转换。)

Swift has an Unmanaged type for that purpose. Swift为此具有Unmanaged类型。 It is a bit cumbersome to use because it works with COpaquePointer instead of UnsafePointer<Void> . 使用它有点麻烦,因为它与COpaquePointer而不是UnsafePointer<Void> Here are two helper methods (named after the Objective-C __bridge cast): 这是两种辅助方法(以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) // ***
}

The "complicated" expression is only necessary to satisfy Swifts strict type system. 仅在满足Swifts严格类型系统时才需要“复杂”表达式。 In the compiled code this is just a cast between pointers. 在编译的代码中,这只是指针之间的强制转换。 (It can be written shorter as indicated in the *** comments if you are willing to use "unsafe" methods, but the compiled code is identical.) (如果您愿意使用“不安全”的方法,可以将其写成更短,如***注释中所示,但是编译后的代码是相同的。)

Using this helper methods you can pass self to a C function as 使用此辅助方法,您可以将self传递给C函数,如下所示:

 let voidPtr = bridge(self)

(or UnsafeMutablePointer<Void>(bridge(self)) if the C function requires a mutable pointer), and convert it back to an object pointer – eg in a callback function – as (如果C函数需要可变的指针, UnsafeMutablePointer<Void>(bridge(self)) ),然后将其转换回对象指针(例如在回调函数中),如下所示:

 let mySelf : MyType = bridge(voidPtr)

No transfer of ownership takes place, so you must ensure that self exists as long as the void pointer is used. 不会发生所有权转移,因此,只要使用void指针,就必须确保self存在。


And for the sake of completeness, the Swift equivalent of __bridge_retained and __bridge_transfer from Objective-C would be 为了完整起见,将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() casts the object pointer to a void pointer and retains the object. bridgeRetained()将对象指针强制转换为void指针,并保留对象。 bridgeTransfer() converts the void pointer back to an object pointer and consumes the retain. bridgeTransfer()将void指针转换回对象指针并使用保留。

An advantage is that the object cannot be deallocated between the calls because a strong reference is held. 优点是,由于持有强引用,因此无法在调用之间释放对象。 The disadvantage is that the calls must be properly balanced, and that it can easily cause retain cycles. 缺点是调用必须适当平衡,并且很容易引起保留周期。


Update for Swift 3 (Xcode 8): 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()
}

The relevant changes to "unsafe pointers" are described in 有关“不安全指针”的相关更改,请参见

It seems to me that this is what withUnsafeMutablePointer is for - to convert an arbitrary Swift pointer into a C pointer. 在我看来,这就是withUnsafeMutablePointer的用途-将任意Swift指针转换为C指针。 So presumably you could do this (I have not tried it, but the code I've tested works safely): 因此,大概可以做到这一点(我没有尝试过,但是我测试过的代码可以安全地工作):

var mself = self 
withUnsafeMutablePointer(&mself) { v in
    let v2 = UnsafeMutablePointer<Void>(v)
    myStruct.inputProcRefCon = v2
}
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()}

This answer doesn't look as topic-specific for a callback as Martin R's answer , but might be of use... 这个答案看起来不像Martin R的答案那样是特定于回调的主题,但可能有用...

You can typically pass a value of any type to an unsafe void pointer using the & operator: 通常,您可以使用&运算符将任何类型的值传递给不安全的void指针:

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

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

However, to pass self you'll need to do so in a context where self is mutable. 但是,要传递self您需要在self易变的环境中进行传递。 That means you'll need to do this in a mutating method (or an init ) of a value type, not a reference type: 这意味着您需要使用值类型而不是引用类型的变异方法(或init )来执行此操作:

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

var myFooValue = FooValue()
myFooValue.bar()

If you want to use a reference type, you'll need to create a local copy of the reference and pass a pointer to that: 如果要使用引用类型,则需要创建引用的本地副本并传递指向该副本的指针:

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

let myFooReference = FooReference()
myFooReference.bar()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将 Swift 结构转换为 UnsafeMutablePointer<Void> - Cast a Swift struct to UnsafeMutablePointer<Void> 如何使用Swift的UnsafeMutablePointer <UnsafeMutablePointer <Void >>引用? - How do I work with a UnsafeMutablePointer<UnsafeMutablePointer<Void>> reference from Swift? Swift 2 - UnsafeMutablePointer <Void> 反对 - Swift 2 - UnsafeMutablePointer<Void> to object 如何传递UnsafeMutablePointer类型的参数 <UnsafePointer<Void> &gt; - How to pass parameter of type UnsafeMutablePointer<UnsafePointer<Void>> Typecast UnsafeMutablePointer <Void> to UnsafeMutablePointer <#Struct type#> - Typecast UnsafeMutablePointer<Void> to UnsafeMutablePointer<#Struct type#> 如何创建UnsafeMutablePointer <UnsafeMutablePointer> 迅速 - How to create UnsafeMutablePointer<UnsafeMutablePointer> in swift 如何构造 UnsafeMutablePointer <Unmanaged<CFData> &gt; 输入 Swift? - How to construct UnsafeMutablePointer<Unmanaged<CFData>> type in Swift? UnsafeMutablePointer <Void> 到具体对象类型 - UnsafeMutablePointer<Void> to Concrete Object Type 如何投射 UnsafeMutableRawPointer! 到 UnsafeMutablePointer<Float> 在 Swift 3.0 或更新版本中? - How to cast UnsafeMutableRawPointer! to UnsafeMutablePointer<Float> in Swift 3.0 or newer? Swift 3中的UnsafeMutablePointer到期望的参数类型UnsafeMutablePointer <_> - UnsafeMutablePointer to expected argument type UnsafeMutablePointer<_> in Swift 3
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM