如何在swift中将self转换为UnsafeMutablePointer类型?

时间:2022-09-11 18:39:08

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?

将“self”转换为unsafemutable指针类型的理想方法是什么?

4 个解决方案

#1


75  

An object pointer (i.e. 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. In Objective-C you would write

对象指针(即引用类型的实例)可以转换为UnsafePointer (const Void *、UnsafeRawPointer in Swift 3中的Swift映射)和back。在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. It is a bit cumbersome to use because it works with COpaquePointer instead of UnsafePointer<Void>. Here are two helper methods (named after the Objective-C __bridge cast):

为此,Swift有一种非托管类型。使用它是有点麻烦的,因为它使用的是cop指针,而不是UnsafePointer 。这里有两个辅助方法(以Objective-C __bridge cast命名):

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. 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.)

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

Using this helper methods you can pass self to a C function as

使用这个helper方法,您可以将self传递给C函数as

 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 – e.g. in a callback function – as

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

 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_retain和__bridge_transfer应该是

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. bridgeTransfer() converts the void pointer back to an object pointer and consumes the retain.

bridgeRetained()将对象指针转换为空指针并保留该对象。bridgeTransfer()将void指针转换回对象指针并使用retain。

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

“不安全指针”的相关更改将在本文中描述

#2


3  

It seems to me that this is what withUnsafeMutablePointer is for - to convert an arbitrary Swift pointer into a C pointer. So presumably you could do this (I have not tried it, but the code I've tested works safely):

在我看来,这就是withUnsafeMutablePointer的用途——将任意的Swift指针转换成C指针。所以你可以这样做(我还没试过,但是我测试过的代码可以安全地工作):

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

#3


2  

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

#4


0  

This answer doesn't look as topic-specific for a callback as Martin R's answer, but might be of use...

这个答案看起来不像马丁·R的回答那样是特定于主题的,但可能是有用的……

You can typically pass a value of any type to an unsafe void pointer using the & operator:

您可以使用&操作符将任何类型的值传递给不安全的空指针:

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

#1


75  

An object pointer (i.e. 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. In Objective-C you would write

对象指针(即引用类型的实例)可以转换为UnsafePointer (const Void *、UnsafeRawPointer in Swift 3中的Swift映射)和back。在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. It is a bit cumbersome to use because it works with COpaquePointer instead of UnsafePointer<Void>. Here are two helper methods (named after the Objective-C __bridge cast):

为此,Swift有一种非托管类型。使用它是有点麻烦的,因为它使用的是cop指针,而不是UnsafePointer 。这里有两个辅助方法(以Objective-C __bridge cast命名):

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. 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.)

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

Using this helper methods you can pass self to a C function as

使用这个helper方法,您可以将self传递给C函数as

 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 – e.g. in a callback function – as

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

 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_retain和__bridge_transfer应该是

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. bridgeTransfer() converts the void pointer back to an object pointer and consumes the retain.

bridgeRetained()将对象指针转换为空指针并保留该对象。bridgeTransfer()将void指针转换回对象指针并使用retain。

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

“不安全指针”的相关更改将在本文中描述

#2


3  

It seems to me that this is what withUnsafeMutablePointer is for - to convert an arbitrary Swift pointer into a C pointer. So presumably you could do this (I have not tried it, but the code I've tested works safely):

在我看来,这就是withUnsafeMutablePointer的用途——将任意的Swift指针转换成C指针。所以你可以这样做(我还没试过,但是我测试过的代码可以安全地工作):

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

#3


2  

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

#4


0  

This answer doesn't look as topic-specific for a callback as Martin R's answer, but might be of use...

这个答案看起来不像马丁·R的回答那样是特定于主题的,但可能是有用的……

You can typically pass a value of any type to an unsafe void pointer using the & operator:

您可以使用&操作符将任何类型的值传递给不安全的空指针:

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