简体   繁体   English

我们可以直接从 Swift 使用基于 API 的 C 结构吗?

[英]Can we use C struct based API directly from Swift?

I walked away from WWDC 2016 with the understanding that we should be wary about using C-based struct API directly from Swift.我离开了 WWDC 2016,了解到我们应该警惕直接从 Swift 使用基于 C 的struct API。 InConcurrent Programming With GCD in Swift 3 , talking about C-based locks, they were very specific:Swift 3 中使用 GCD 进行并发编程中,谈到基于 C 的锁,它们非常具体:

... And in Swift, since you have the entire Darwin module at your disposition, you will actually see the struct based traditional C locks. ...在 Swift 中,由于您拥有整个 Darwin 模块,您实际上会看到基于struct的传统 C 锁。 However, Swift assumes that anything that is struct can be moved, and that doesn't work with a mutex or with a lock.但是,Swift 假设任何struct都可以移动,并且这不适用于互斥体或锁。 So we really discourage you from using these kind of locks from Swift.因此,我们真的不鼓励您使用 Swift 中的此类锁。 ... ...

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

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.然后,您将公开lockunlock方法,如果您还需要它,还有一个tryLock ,当您将这个 class 子类化时,您将能够从 Swift 调用它。 ... ...

 @implementation LockableObject { os_unfair_lock _lock; } - (void)lock { os_unfair_lock_lock(&_lock); } - (void)unlock { os_unfair_lock_unlock(&_lock); } @end

However, watching WWDC 2019Developing a Great Profiling Experience , I notice that the author is using os_unfair_lock directly from Swift, without this Objective-C wrapper, effectively:但是,在观看 WWDC 2019Developing a Great Profiling Experience时,我注意到作者是直接从 Swift 使用os_unfair_lock ,没有这个 Objective-C 包装器,有效:

private var workItemsLock = os_unfair_lock()

func subWorkItem(...) {
    ...
    os_unfair_lock_lock(&self.workItemsLock)
    ...
    os_unfair_lock_unlock(&self.workItemsLock)
    ...
}

Empirically, this sort of direct use of os_unfair_lock appears to work, but that doesn't mean anything.根据经验,这种直接使用os_unfair_lock似乎可行,但这并不意味着什么。 Respecting the caveat in the 2016 WWDC video, I have refrained from using os_unfair_lock directly from Swift.尊重 2016 年 WWDC 视频中的警告,我避免直接从 Swift 使用os_unfair_lock

So, the question is, are they being (ever so slightly) sloppy in the use of this API in this 2019 sample?所以,问题是,他们在 2019 年的样本中使用这个 API 是否(稍微)草率? Or was the 2016 video incorrect in its claims?还是 2016 年的视频在其声明中不正确? Or has the handling of C-based struct changed since Swift 3, now rendering this pattern safe?还是自 Swift 3 以来基于 C 的struct的处理发生了变化,现在使这种模式安全?

The API example of using private var workItemsLock = os_unfair_lock() can fail at runtime.使用private var workItemsLock = os_unfair_lock()的 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 .来自 C 的线程原语需要一个稳定的 memory 位置,因此要使用它们或另一个直接将这些原语之一作为其成员的结构,您必须使用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.原因是UnsafePointer API 在分配了一块 memory 后,memory 是稳定的,不能被编译器移动或轻易复制。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM