【问题标题】:.c File via Bridging Header Not Working After Xcode 8 Update.c 文件通过桥接头在 Xcode 8 更新后不起作用
【发布时间】:2017-02-05 18:10:12
【问题描述】:

我一直在开发的应用程序使用了一个外部库 pdlib,它有自己的外部库(.c 文件),我通过桥接头 #import "Uzi.c" 导入并通过 Uzi 调用我的主 Swift 文件.c 的设置函数Uzi_setup() 在我的ViewController 类中。直到几天前更新到新的公共 Xcode 8 之后,我才对此没有任何问题(我在夏季对 Xcode 8 Beta 1 没有任何问题)。

这是我得到的 7 个错误,列在一个“Mach-O 链接器错误”保护伞下:

Undefined symbols for architecture x86_64:
"_Uzi_bang", referenced from:
  _Uzi_setup in ViewController.o
"_Uzi_class", referenced from:
  _Uzi_setup in ViewController.o
"_Uzi_float", referenced from:
  _Uzi_setup in ViewController.o
"_Uzi_new", referenced from:
  _Uzi_setup in ViewController.o
"_Uzi_pause", referenced from:
  _Uzi_setup in ViewController.o
"_Uzi_resume", referenced from:
  _Uzi_setup in ViewController.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

那些未定义的符号是来自 Uzi.c 的 6 个函数和一个类声明。这是整个c文件的链接:https://github.com/electrickery/pd-miXedSon/blob/master/hammer/Uzi.c

我已经尝试了我在网上找到的用于处理类似问题的所有解决方案,但还没有解决方案...我尝试将“架构”和“有效架构”设置更改为仅 armv7 和 armv7s(无 arm64)和将“仅构建活动架构”更改为“否”。这些步骤似乎对处于类似情况的其他人有所帮助,但它们对我不起作用(并且去掉 arm64 会导致出现额外的错误)。

XCode 8 是相当新的版本(公共版本于 9 月 13 日发布),因此几乎没有其他关于此升级的问题会导致类似问题。

任何帮助将不胜感激!

【问题讨论】:

  • Undefined reference C++的可能重复
  • @Olaf 我看不到我的 .C 文件被多次链接的任何方式。其他参考似乎不适用于我的问题,但如果适用,你能告诉我它是怎么回事吗?
  • 这是.C 还是.c 文件?第一个是 C++,而不是 C。
  • @Olaf 这是一个.c 文件(我在问题标题中更正了)。我的大部分应用程序都是用 Swift 编写的。我只是通过桥接头链接到这个外部。在最新的 Xcode 8 发布之前,我在执行此操作时遇到的问题为零。
  • C 文件是可执行文件的目标成员吗?

标签: ios c swift linker-errors libpd


【解决方案1】:

由@danomatika 在 GitHub 上解决:https://github.com/libpd/libpd/issues/149

“您通常不应包含/导入实现文件,即 .c、.cpp、.m 等。这是导致重复符号问题的原因。

这就是头文件中的“前向函数声明”的作用:告诉编译器一个函数存在以及它需要/返回什么数据。然后编译器假定函数的实际实现存在于实现文件中。如果找不到,则会收到“未定义符号错误”。如果你以某种方式最终声明了函数两次,也就是在 .c 文件中包含带有前向声明的标头和函数本身的实现,那么你会得到一个“重复符号错误”。

这都是低级的东西,只是一个真正的问题,因为 Pd 外部是围绕动态库设计的,所以没有构建或提供包含函数声明的头文件。这就是为什么你必须做一些额外的工作并自己做。

它们有两个简单的解决方法,都涉及在头文件中声明要从 .c 文件调用的所需函数。

  1. 只需在桥接头中声明函数即可:

    void uzi_setup();

  2. 创建一个标头,例如 Externals.h,并在其中声明所有外部内容:

    // forward declare setup functions only found in .c implementations void uzi_setup();

    // convenience wrapper function void externals_setup() { uzi_setup(); }

    然后在你的桥接头中导入文件:

    #import "Externals.h"

    您现在可以在 swift 中执行以下操作:

    externals_setup()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-04
    • 2016-09-03
    • 2017-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    • 2018-09-26
    相关资源
    最近更新 更多