Как направить себя в UnsafeMutablePointer type в swift
Пытаясь передать «self» функции C в swift, при вызове следующего кода:
var callbackStruct : AURenderCallbackStruct = AURenderCallbackStruct.init( inputProc: recordingCallback, inputProcRefCon: UnsafeMutablePointer )
Каков идеальный способ включить «я» в тип UnsafeMutablePointer?
- Каковы различия между переменной указателя и ссылочной переменной в C ++?
- Обращение строки в C
- Что такое nullptr?
- В чем разница между char array vs char pointer в C?
- Почему int указатель «++» увеличивается на 4, а не на 1?
- C typedef указателя на структуру
- Имеют ли эти утверждения о указателях одинаковый эффект?
- Это хорошая идея для указателей typedef?
- C не так сложно: void (* (* f ) ()) ()
- Почему в C ++ не существует ссылки на член?
- Указатель функции Typedef?
- Сколько уровней указателей у нас есть?
- Изменение константы с помощью указателя не const
Указатель объекта (т. UnsafePointer
Экземпляр ссылочного типа ) может быть преобразован в UnsafePointer
(Swift-сопоставление const void *
, UnsafeRawPointer
в Swift 3) и обратно. В Objective-C вы должны написать
void *voidPtr = (__bridge void*)self; // MyType *mySelf = (__bridge MyType *)voidPtr;
(См. 3.2.4 Мостовые листы в документации Clang ARC для точного значения этих отливок.)
Для этой цели Swift имеет Unmanaged
тип. Это немного громоздко использовать, потому что он работает с COpaquePointer
вместо UnsafePointer
. Вот два вспомогательных метода (названных в честь __bridge
Objective-C __bridge
cast):
func bridge(obj : T) -> UnsafePointer { return UnsafePointer(Unmanaged.passUnretained(obj).toOpaque()) // return unsafeAddressOf(obj) // *** } func bridge(ptr : UnsafePointer) -> T { return Unmanaged.fromOpaque(COpaquePointer(ptr)).takeUnretainedValue() // return unsafeBitCast(ptr, T.self) // *** }
«Сложное» выражение необходимо только для того, чтобы удовлетворить систему строгих типов Swifts. В скомпилированном коде это просто бросок между указателями. (Он может быть написан короче, как указано в комментариях ***
если вы готовы использовать «небезопасные» методы, но скомпилированный код идентичен.)
Используя эти вспомогательные методы, вы можете передать self
функции C, как
let voidPtr = bridge(self)
(или UnsafeMutablePointer
если для функции C требуется переменный указатель) и преобразовать его обратно в указатель объекта – например, в функцию обратного вызова – как
let mySelf : MyType = bridge(voidPtr)
Передача владения не происходит, поэтому вы должны убедиться, что self
существует, пока используется указатель void.
И для полноты, эквивалент __bridge_retained
и __bridge_transfer
от Objective-C будет
func bridgeRetained(obj : T) -> UnsafePointer { return UnsafePointer(Unmanaged.passRetained(obj).toOpaque()) } func bridgeTransfer(ptr : UnsafePointer) -> T { return Unmanaged.fromOpaque(COpaquePointer(ptr)).takeRetainedValue() }
bridgeRetained()
указатель на указатель на пустоту и сохраняет объект. bridgeTransfer()
преобразует указатель void обратно в указатель объекта и потребляет сохранение.
Преимущество заключается в том, что объект не может быть освобожден между вызовами, потому что поддерживается сильная ссылка. Недостатком является то, что вызовы должны быть правильно сбалансированы и что они могут легко вызвать циклы сохранения.
Обновление для Swift 3 (Xcode 8):
func bridge(obj : T) -> UnsafeRawPointer { return UnsafeRawPointer(Unmanaged.passUnretained(obj).toOpaque()) } func bridge (ptr : UnsafeRawPointer) -> T { return Unmanaged .fromOpaque(ptr).takeUnretainedValue() } func bridgeRetained (obj : T) -> UnsafeRawPointer { return UnsafeRawPointer(Unmanaged.passRetained(obj).toOpaque()) } func bridgeTransfer (ptr : UnsafeRawPointer) -> T { return Unmanaged .fromOpaque(ptr).takeRetainedValue() }
Соответствующие изменения в «небезопасных указателях» описаны в
- SE-0017 Изменить Неуправляемое использование UnsafePointer
- SE-0107 UnsafeRawPointer API
Мне кажется, что это то, что с помощью withUnsafeMutablePointer
– для преобразования произвольного указателя Swift в указатель C. Так что предположительно вы могли бы это сделать (я не пробовал, но проверенный мной код работает безопасно):
var mself = self withUnsafeMutablePointer(&mself) { v in let v2 = UnsafeMutablePointer(v) myStruct.inputProcRefCon = v2 }
func bridge(obj : T) -> UnsafePointer { return UnsafePointer(Unmanaged.passUnretained(obj).toOpaque()) } func bridge(ptr : UnsafePointer) -> T { return Unmanaged.fromOpaque(ptr).takeUnretainedValue() } func bridgeRetained (obj : T) -> UnsafePointer { return UnsafePointer( Unmanaged.passRetained(obj).toOpaque())} func bridgeTransfer(ptr : UnsafePointer) -> T { return Unmanaged.fromOpaque(ptr).takeRetainedValue()}
Этот ответ не выглядит как конкретный для обратного вызова, как ответ Мартина R , но может быть полезным …
Обычно вы можете передать значение любого типа в небезопасный указатель void с помощью оператора &
:
func baz(p: UnsafeMutablePointer) -> 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()