我正在從 Swift 呼叫一個 C 庫,它接收一個不透明的指標和一個回呼函式。然后,C 庫將該不透明指標傳遞給回呼函式。為了創建不透明指標,我使用了 Swift 標準庫提供的非托管型別,它看起來像這樣:
func callback(
opaque: UnsafeMutableRawPointer?,
) {
let queue: DispatchQueue = // ...
let thing = Unmanaged<MyThing>.fromOpaque(opaque).takeRetainedValue()
queue.async { [weak thing] in
guard let thing else { return }
// Use thing here
}
}
func newThing() -> MyThing {
let thing = MyThing()
let opaque = Unmanaged.passUnretained(thing).toOpaque()
my_c_library_function(opaque, callback) // invokes callback(opaque)
return thing
}
class MyThing {
}
我遇到的問題是thing
在callback
. 我猜這是因為我創建了一個新的 Unmanaged 實體,呼叫了 takeRetained,然后在回呼結束時釋放了該值。thing
我仍然參考inside of的事實newThing
不被視為Unmanaged
in 實體的一部分callback
。
有沒有辦法解決這個問題?我試圖用這種模式解決的主要問題是從 C 庫中獲取指向 MyThing 的指標,然后在異步塊中使用該指標。newThing
理想情況下,如果呼叫者仍然有對它的參考,我只想執行異步塊。
uj5u.com熱心網友回復:
我認為問題在于我通過了未保留,但隨后保留了保留,因此保留計數不正確。
確實,這是問題之一。如果 C 函式是同步的,則應該傳遞 unretained 并取 unretained,因為不需要保留參考。的實體myThing
將保持活動狀態,因為在呼叫newThing
時保留它。callback
但是,您使用的方式queue.async
是有問題的。你不應該thing
在那里軟弱地捕捉。由于queue.async
是異步的,它會在callback
回傳后運行。那時,實體已經被釋放,您guard
將失敗并立即回傳。
你應該這樣做:
queue.async {
// do things with thing, e.g.
print(thing)
}
這會導致傳遞async
給 retain的閉包thing
。
如果 C 函式是異步的,則應改為傳遞 reserved 和 take reserved。這是因為在這種情況下,回呼將在 newThing
回傳后運行,此時不會保留thing
.
同樣,您也不應thing
在queue.async
.
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/533058.html
標籤:迅速