Как направить себя в UnsafeMutablePointer type в swift

Пытаясь передать «self» функции C в swift, при вызове следующего кода:

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

Каков идеальный способ включить «я» в тип UnsafeMutablePointer?

Указатель объекта (т. 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(bridge(self)) если для функции 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() 
  • Разница между char * var; и char * var ;?
  • Какова точка указателей на функции?
  • Проверка, является ли это нулевым
  • Странное поведение с const_cast
  • Динамическое распределение массива объектов
  • C ++: указатель на элемент данных classа ":: *"
  • C ++ Возвращаемый массив многомерности из функции
  • Ближние и дальние указатели
  • Объявление указателей; звездочку слева или справа от пространства между типом и именем?
  • Приемник значений против приемника указателя в Голанге?
  • Как сделать буквенный * int64 в Go?
  • Давайте будем гением компьютера.