我们可以直接从 Swift 使用基于 C 结构的 API 吗? [英] Can we use C struct based API directly from Swift?
问题描述
我离开 WWDC 2016 时了解到我们应该警惕直接从 Swift 使用基于 C 的 struct
API.在 在 Swift 3 中使用 GCD 进行并发编程中,谈到基于 C 的锁,它们非常具体:
I walked away from WWDC 2016 with the understanding that we should be wary about using C-based struct
API directly from Swift. In Concurrent Programming With GCD in Swift 3, talking about C-based locks, they were very specific:
... 而在 Swift 中,由于您拥有整个 Darwin 模块,您实际上会看到基于 struct
的传统 C 锁.但是,Swift 假定任何 struct
都可以移动,并且这不适用于互斥锁或锁.所以我们真的不鼓励你使用 Swift 的这些类型的锁....
... And in Swift, since you have the entire Darwin module at your disposition, you will actually see the
struct
based traditional C locks. However, Swift assumes that anything that isstruct
can be moved, and that doesn't work with a mutex or with a lock. So we really discourage you from using these kind of locks from Swift. ...
...如果你想要一些...看起来像你在C中拥有的锁,那么你必须调用Objective-C并在Objective-C中引入一个基类,将你的锁作为ivar.
... And if you want something ... that looks like the locks that you have in C, then you have to call into Objective-C and introduce a base class in Objective-C that has your lock as an ivar.
然后你将公开 lock
和 unlock
方法,以及一个 tryLock
如果你需要它,你将能够当您将此类子类化时,请从 Swift 调用....
And then you will expose lock
and unlock
methods, and a tryLock
if you need it as well, that you will be able to call from Swift when you will subclass this class. ...
@implementation LockableObject {
os_unfair_lock _lock;
}
- (void)lock { os_unfair_lock_lock(&_lock); }
- (void)unlock { os_unfair_lock_unlock(&_lock); }
@end
但是,观看 WWDC 2019 开发出色的分析体验,我注意到作者直接从 Swift 使用 os_unfair_lock
,没有使用这个 Objective-C 包装器,有效地:
However, watching WWDC 2019 Developing a Great Profiling Experience, I notice that the author is using os_unfair_lock
directly from Swift, without this Objective-C wrapper, effectively:
private var workItemsLock = os_unfair_lock()
func subWorkItem(...) {
...
os_unfair_lock_lock(&self.workItemsLock)
...
os_unfair_lock_unlock(&self.workItemsLock)
...
}
根据经验,这种对 os_unfair_lock
的直接使用似乎有效,但这并不意味着什么.尊重 2016 年 WWDC 视频中的警告,我没有直接从 Swift 使用 os_unfair_lock
.
Empirically, this sort of direct use of os_unfair_lock
appears to work, but that doesn’t mean anything. Respecting the caveat in the 2016 WWDC video, I have refrained from using os_unfair_lock
directly from Swift.
那么,问题是,在 2019 年的示例中,他们在使用此 API 时是否(有一点点)马虎?还是 2016 年视频的声明不正确?还是自 Swift 3 以来基于 C 的 struct
的处理发生了变化,现在使这种模式安全?
So, the question is, are they being (ever so slightly) sloppy in the use of this API in this 2019 sample? Or was the 2016 video incorrect in its claims? Or has the handling of C-based struct
changed since Swift 3, now rendering this pattern safe?
推荐答案
使用 private var workItemsLock = os_unfair_lock()
的 API 示例可能会在运行时失败.
The API example of using private var workItemsLock = os_unfair_lock()
can fail at runtime.
来自 C 的线程原语需要一个稳定的内存位置,因此要使用它们或另一个直接将这些原语之一作为其成员的结构,您必须使用 UnsafePointer
.这样做的原因是 UnsafePointer
API 一旦分配了一块内存,该内存是稳定的,并且不能被编译器移动或简单地复制.
The threading primitives from C need a stable memory location so to use them or another struct that has one of these primitives directly as a member of it you have to use UnsafePointer
. The reason for this is that UnsafePointer
APIs once they have allocated a chunk of memory that memory is stable and cannot be moved or trivially be copied by the compiler.
如果您像这样更改示例,它现在有效
If you change the example like this it is now valid
private var workItemsLock: UnsafeMutablePointer<os_unfair_lock> = {
// Note, somewhere else this will need to be deallocated
var pointer = UnsafeMutablePointer<os_unfair_lock>.allocate(capacity: 1)
pointer.initialize(to: os_unfair_lock())
return pointer
}()
func subWorkItem(...) {
...
os_unfair_lock_lock(self.workItemsLock)
...
os_unfair_lock_unlock(self.workItemsLock)
...
}
这篇关于我们可以直接从 Swift 使用基于 C 结构的 API 吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!