从 Swift 5.3 版调用 C 函数:使用 pthreads

Posted

技术标签:

【中文标题】从 Swift 5.3 版调用 C 函数:使用 pthreads【英文标题】:Calling C function from Swift version 5.3: using pthreads 【发布时间】:2021-05-24 21:13:53 【问题描述】:

EDIT3:从 RDerik 的代码中重新创建错误

我最初是从我从 RDerik 修改的代码开始的。现在,其他人可能会重新创建错误,我正在运行从 here 克隆的 RDerik 未修改的代码。

当我运行 RDerik 的代码时,我得到以下错误(我在 EDIT 中记录的相同错误:下面):

错误:可选类型“pthread_t?”的值(又名“可选”)必须解包为“pthread_t”(又名“UInt”)类型的值

注意:如果可选值包含 nil,则使用 ! 强制解包以中止执行

错误:无法转换类型 '(UnsafeMutableRawPointer) -> UnsafeMutableRawPointer?' 的值到预期的参数类型'@convention(c) (UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer?' let result = pthread_create(&myThread, nil, threadedFunction, pThreadParameter)

我通过将threadedFunction()的函数头更改为:

func threadedFunction(pointer: UnsafeMutableRawPointer!) -> UnsafeMutableRawPointer? 

原帖:

我知道这个问题之前已经回答过,但我无法找到与 Swift 5.3 兼容的修复程序。 我需要调用的 C 函数有这个签名:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg)

下面的第 5 行是我调用pthread_create() 的 Swift 尝试。具体来说,我的问题在于第一个参数:&myThread

我的密码:(修改自here)

var myThread: pthread_t! = nil
var threadParameter  = _ThreadParameter(threadIdentifier: _ThreadIdentifier(id: ""), pxT: self)
var pThreadParameter = UnsafeMutablePointer<_ThreadParameter>.allocate(capacity:1)
pThreadParameter.pointee = threadParameter
let result = pthread_create(&myThread, nil, __threadedFunction, pThreadParameter)

错误:

调用 pthread_create 时,myThread 参数会引发以下错误: 致命错误:在隐式展开 Optional 值时意外发现 nil,第 5 行

编辑:

我尝试过的其他事情:

如果我对 pthread 使用 ? 而不是 !,如下所示:

    var myThread: pthread_t? = nil

我得到编译错误:

错误:可选类型“pthread_t?”的值(又名“可选”)必须解包为“pthread_t”(又名“UInt”)类型的值

注意:使用 '!' 强制展开如果可选值包含'nil'则中止执行

EDIT2:

也试过了:

    let result = pthread_create(&myThread, 0, __threadedFunction, pThreadParameter)

错误:无法将“Int”类型的值转换为预期的参数类型“UnsafePointer?”

【问题讨论】:

好帖子,有有用的链接:***.com/a/63332736/421195 出于好奇,为什么您需要专门调用pthread_create,而不是使用 Swift 可用的其他并发范例之一(例如 Dispatch)? 附加建议:在这种情况下,我经常发现创建一个小的“测试用例”非常有帮助。一些额外的前期工作......但可以节省大量时间来获得您需要的解决方案。试试这个:1)下载这个项目:github.com/rderik/rdknitting 2)完成相应的教程:rderik.com/blog/multithreading-with-pthreads-in-swift。 3) 一旦你的测试用例工作起来,将解决方案应用到你的实际项目中。 4) 如果您在环境中遇到 RDerick 代码问题,请发布新的 SO 问题。 ALSO:你试过有线的suggestion:let result = pthread_create(&amp;myThread, 0, __threadedFunction, pThreadParameter)吗?发生了什么? 鉴于您发布的代码,我无法重现这一点,但我不得不对您的代码与您链接到的代码有何不同做出很多猜测(例如,您已将在不同的地方下划线它们不在原始代码中,并且您的 ThreadParameter 不同)。你能发布一个完整的例子来重现它吗? 【参考方案1】:

我不知道斯威夫特。然而,在 c.NULL 中,对应于 NILNULL 又是一个宏,具体取决于编译器。所以它既可以定义为#define NULL ((char *)0),也可以简单地定义为#define NULL 0。那么如果你传递 pthread_create(&amp;myThread, 0, ... 而不是 nil 会发生什么?

【讨论】:

谢谢@wired。我尝试了您的建议,并在我的原始帖子中的 EDIT2 下发布了结果。 如前所述,我不知道 swift,但这个链接可能会有所帮助,因为它处理 a) swift & pthreads b) 不安全指针 ***.com/questions/26449990/… Swift 的 nil 与 C 的 NULL 不同。在 ObjC 中,这基本上是正确的,但在 Swift 中则不然。 nilOptional&lt;T&gt;.none 相同。当桥接到 C(通过 ObjC)时,它可以被翻译成 0,但你不能在 Swift 中这样替换它。

以上是关于从 Swift 5.3 版调用 C 函数:使用 pthreads的主要内容,如果未能解决你的问题,请参考以下文章

从 Swift 4 调用 C 函数

从 Swift 调用 Objective C 和 C 传递回调函数

从 Swift 调用带有数组指针和 int 指针的 C 函数

从 C 调用 Swift 的最佳方法是啥?

从 Swift 调用 Objective C 自定义初始化函数

从 Laravel 5.2 更新到 5.3 后,调用数组上的成员函数 all()