在 Objective-C 中使用外部 C++ 头文件

Posted

技术标签:

【中文标题】在 Objective-C 中使用外部 C++ 头文件【英文标题】:Use of external C++ headers in Objective-C 【发布时间】:2013-07-02 04:48:28 【问题描述】:

在我的 ios 项目中,我需要使用一个用 C++ 编写的外部库。 C++ 头文件都在一个目录中。

我已将这些 C++ 标头添加到我的 Xcode 项目中,并且还指定了标头搜索路径(在构建设置中)。

问题是这些 C++ 标头使用 尖括号相互包含。这导致:

'filename.h' file not found with <angled> include, use "quotes" instead.

奇怪的是 Xcode 并没有抱怨所有的头文件。同样的标题#include'd 在一个文件中也很好,而在另一个文件中#include'd 时会出现问题。我认为这是由于这些标头#include 彼此造成的。

    为什么搜索路径不起作用? 有没有办法在不修改这些头文件的情况下解决这个问题?

谢谢!

【问题讨论】:

你有那个 C++ 库的源代码和 Xcode 项目吗? @CouchDeveloper 不,我没有。 设置“始终搜索用户路径”构建设置有帮助吗? @MartinR 天哪,是的! :-) 把它作为答案,我会奖励。我已经删除了-I,很好。为什么-I 不起作用? 【参考方案1】:
#include <bla.h>

用于标准库或框架头文件,以及搜索策略 与用于

的不同
#include "bla.h"

参见示例

What is the difference between #include <filename> and #include "filename"?

作为一种解决方法,您可以将 Xcode 构建设置“始终搜索用户路径”设置为 YES。

【讨论】:

请注意,将“始终搜索用户路径”设置为“是”可能会导致标题问题。强烈建议将其设置为 NO,这是正确的方法。它仍然只是为了向后兼容。第三方库的标头应包含在尖括号中。 @CouchDeveloper:这是一种解决方法,但您是对的,您的答案可能是更好的解决方案。 @CouchDeveloper 同意此设置应设置为 NO,但是在构建嵌入式框架的上下文中将此设置设置为 YES 有什么不希望的吗?【参考方案2】:

从一个“空白”应用项目开始:

    在应用程序的项目中创建一个文件夹“Libraries” - 最好作为 MyApp.xcodeproj 文件的同级,但它可以在任何地方。为每个配置(Debug、Release 等)创建子文件夹,并可能为每个架构(armv7、armv7s、arm64)创建子文件夹,除非二进制文件是包含所有架构的通用二进制存档。

    获取第三方库和静态库二进制文件的头文件(对于不同的平台、配置和架构可能不止一个),并将它们移动到“库”文件夹中的相应子文件夹中(您可能需要创建):

    例如,假设您有一个通用二进制文件(armv7、armv7s、arm64)以及该库的调试和发布版本: 现在,假设文件夹结构如下:

    $(SRCROOT)/Libraries
        Debug-iphoneos
            include
                ThirdParty
                    third_party.hh 
                    ...
            libThirdParty.a             
        Release-iphoneos
            include
                ThirdParty
                    third_party.hh 
                    ...
            libThirdParty.a             
    MyApp.xcodeproj            
    

    “库搜索路径”构建设置:

    将“Libraries”文件夹拖到您的 Xcode 项目中。这可能会在构建设置中自动创建一个库搜索路径。请验证这一点,如果不正确,请修复它。

    给定示例,为调试和发布配置添加以下库搜索路径:

    调试:库搜索路径$(SRCROOT)/Libraries/Debug-iphoneos

    发布:图书馆搜索路径$(SRCROOT)/Libraries/Release-iphoneos

    对于特定的配置和目标平台对,您可能有不同的库搜索路径。相应地在构建设置中设置不同的路径。

    “标题搜索路径”构建设置:

    给定示例,将以下标头搜索路径添加到调试和发布配置:

    调试:标头搜索路径$(SRCROOT)/Libraries/Debug-iphoneos/include

    发布:标题搜索路径$(SRCROOT)/Libraries/Release-iphoneos/include

    同样,对于特定的 Config/Target 对,您可能有不同的路径 - 尽管标头可能相同。

    通过将 -lc++ 添加到 Other Linker Flags 构建设置,将您的应用与 C++ 标准库链接。

    在您的文件中导入标头,如下所示:

     #import <ThirdParty/third_party.hh>
    

【讨论】:

这很有帮助,因为在我的情况下,该错误取决于目标。 史诗,我第一次可以使角度包括使用我项目中的第 3 方库,因为我想修补它。谢谢。【参考方案3】:

在 Xcode 9 中,我需要将头文件路径添加到 Header Search Paths 构建设置,而不是 User Header Search Paths

Xcode 会将User Header Search Paths 附加到编译命令作为-iquote 选项,但附加Header Search Paths 作为-I 选项。这是关键的区别。

【讨论】:

感谢您指出这一点。 (不过我没时间检查,我相信你。)【参考方案4】:

在 XCode 中,将“用户标题搜索路径”设置为指向您的库目录后,您还必须确保将名为“始终搜索用户路径”的字段设置为“是”

这解决了我遇到的问题:使用 包含找不到 文件,请改用“引号”。

【讨论】:

【参考方案5】:

我的两分钱用于 OSX / mysql。 (顺便问一下,为什么在 mysql 中虚假使用 ......无论如何......)

根据 Xcode 11 警告,“强烈建议禁用它。”,

我更喜欢修补另一个设置,将“始终搜索用户路径”保留为“否”。

我设置:

HEADER_SEARCH_PATHS = "/usr/local/mysql/include"。

链接器:

我) 如果出现链接错误,通常在“/usr/local/mysql/lib”中添加“libmysqlclient.a”,只需从Finder中拖动即可)

II:你可能会遇到最严重的错误......

"/usr/local/lib/libmysqlclient.21.dylib: (/usr/local/lib/libmysqlclient.21.dylib) 中的代码签名在使用库验证的进程中无效: 映射进程和映射文件 (非平台)具有不同的团队 ID”

因为那个库没有签名。只需在 Entitlemens 中:

(在 XML 中): ..

<dict>
    <key>com.apple.security.cs.disable-library-validation</key>
    <true/>
</dict>
...

【讨论】:

以上是关于在 Objective-C 中使用外部 C++ 头文件的主要内容,如果未能解决你的问题,请参考以下文章

Objective-c 头文件中的 C++ 类声明

Objective-C 使用 C++类

Objective-C 静态、外部、公共变量

C 与 C++ 中的外部函数

NSStringto类成员分配崩溃

在类的头文件里尽量少引入其它头文件 &lt;&lt;Effective Objective-C&gt;&gt;