【问题标题】:How to use Superpowered lib in Swift project如何在 Swift 项目中使用 Superpowered lib
【发布时间】:2016-03-16 14:48:35
【问题描述】:

我想用 Swift 制作一个应用程序,只需通过 iPhone 的麦克风录制,然后播放录制的声音。

为此,我想使用 lib Superpowered,它是一个带有头文件的静态库。

为此,我尝试在我的项目中拖放 .a 和头文件(Xcode 为我创建一个桥接头文件),在 Xcode > Target > General 的“Linked Frameworks and Libraries”中添加 .a(所以在 Xcode > Target > Build phase > "Link Binary With Libraries" 中)并在 Xcode > Target > Build Settings > Search Paths > Library Search Paths 中索引 .h 文件路径。

但是我有错误“ld:未找到架构 arm64 的符号” 和这里XCode: Undefined symbols for architecture arm64 error完全一样,我尝试了我在网上找到的所有解决方案,仍然无法编译。

所以!

Superpowered 为我们提供了一个示例应用程序,以展示如何在 Swift 项目中混合使用 Objective-C++ 并使用它们的库(如果您需要 https://github.com/superpoweredSDK/Low-Latency-Android-Audio-iOS-Audio-Engine,这里是 git 的链接)。

这是示例项目的一些截图,其中包含我理解的和我不理解的:

带有我想在我的 Swift 代码中使用的 lib 方法原型的 Bridging-Header-File(我不喜欢这个,但如果它是唯一的方法......)。

Swift 代码所在的 viewController 文件,感谢 Bridging-Header-File,我可以在其中创建 Superpowered 对象,并调用我放入其中的方法。

而且我什至不明白为什么这个 Objective-C++ 文件在这里以及它包含什么。它无处不在,甚至它们的 lib 文件也没有。

考虑到这个示例项目,我创建了自己的项目,这里是一些截图:

与示例项目中相同的 Bridging-Header-File,除了我包含 SuperpoweredIOSAudioIO.h 以便我可以使用 SuperpoweredIOSAudioIODelegate

我的 viewController 文件在 Swift 中的代码所在的位置,感谢 Bridging-Header-File,我可以在其中创建超级对象,并调用我放入其中的方法。

到这里为止,一切都很好,只是我不能例如创建SuperpoweredRecorder 对象。如果我尝试在我的 Bridging-Header-File 中包含 SuperpoweredRecorder.h 文件,则会出现以下错误:

所以我看到这是因为SuperpoweredRecorder.h 包含一些 .cpp 文件,我必须为 cpp 创建一个包装器(有点像我对桥接头所做的,不是吗?)但其中包括一个 .h 和一个.mm 文件,我不知道我必须在那个 .mm 文件中放什么(SuperpoweredRecorder.cpp 的代码?但我无权访问它)

所以是的,我对所有这些东西有点困惑,你能帮我理解如何在我的 Swift 项目中使用所有 Superpowered 库吗?

【问题讨论】:

    标签: c++ ios swift objective-c++


    【解决方案1】:

    正如我在@OmniProg 的评论中所说,我与 Superpowered 的 CTO 进行了一些交谈,这对我找到以下解决方案很有帮助。

    所以,由于 Swift 不能直接与 C++ 交互,但可以与 Objective-C 交互,我必须在 Objective-C++(.mm 文件,C++ 和 Objective-C 的混合体)中创建对象,这些对象包装了 lib Superpowered 的 C++ 类.

    这是一个来自 lib 的 SuperpoweredRecorder 对象的示例:

    在这里,我创建了一个 .h 文件,我在其中创建了名为 SuperpoweredRecorderWrapped 的包装器原型,并且我还在其中创建了我想要使用的 lib 的 SuperpoweredRecorder 的所有方法的原型。

    然后我创建一个新的 .m 文件,我将其重命名为 .mm 并在其上实现 SuperpoweredRecorderWrapped。 我同时导入了SuperpoweredRecorderWrapped.hSuperpoweredRecorder.h。 我创建了一个SuperpoweredRecorder 对象作为名为@9​​87654334@ 的属性,在我的方法中,我调用了_wrapped 对象的相应方法。 有了这个,当我在我的 Swift 代码中调用 SuperpoweredRecorderWrappedstart 时,这个将调用 _wrappedstart,一个 SuperpoweredRecorder 对象。看到诀窍了吗?

    最后我在我的 Bridging-Header 中包含所有包装的类,这样我就可以从 Swift 实例化我的包装对象。

    注意:所有 C++ 代码都必须在 .mm 文件中,这就是为什么我在我的 .mm 文件中而不是在我的 .h 中包含 C++ 代码的 .h 的 #include文件。

    【讨论】:

    • 我使用了类似的技巧来包装C++,但是,问题是一些依赖找不到,例如:Undefined symbols for architecture x86_64: "_AVURLAssetPreferPreciseDurationAndTimingKey",引用自:__ZL9makeAssetPKcb在 libSuperpoweredAudioOSX.​​a(ipodreader.o) 检查这个问题的详细信息:github.com/superpoweredSDK/…
    • 嗨 @YoanGJ,在 swift 项目中集成 SuperpoweredFrequencyDomain 时,我需要您的帮助...
    • 嗨@Mr.Ahtazaz 我已经好几年没使用这个库了,所以我不知道我是否可以帮忙,但我会尝试...告诉我
    • 感谢您的友好回复@YoanGJ。成功集成,但我在实施 SuperPoweredEcho 时需要帮助
    • 你能给我你的邮箱@YoanGJ
    【解决方案2】:

    我没有使用 Objective-C++ 编程,但我确实有使用 C、C++、Objective-C 和 Swift 的经验,所以这里有一些基于查看 Superpowered SDK 和示例代码的观察和想法。

    桥接头让 Swift 直接与 Objective-C 接口,由于 Objective-C 是 C 的严格超集,这也意味着与 C 接口。但是,您不能直接与 C++ 交互,而这正是 Objective-C++ 的用武之地。从我所看到的情况来看,您可以在 Objective-C++ 中混合使用 Objective-C 和 C++ 代码,这允许 Objective-C 使用 C++ 类。

    现在谈谈一些细节。

    您查看的 SuperpoweredFrequencies 示例中的桥接头引入了一个 Objective-C 类 Superpowered,它不是库的一部分,而是示例的一部分,并在Superpowered.mm。它是一个 Objective-C++ 文件,因为Superpowered 调用了一些 C++ 代码。

    查看Superpowered.mm,您会看到它导入了Objective-C 标头:

    #import "SuperpoweredFrequencies-Bridging-Header.h"
    #import "SuperpoweredIOSAudioIO.h"
    

    以及 C 和 C++ 头文件:

    #include "SuperpoweredBandpassFilterbank.h"
    #include "SuperpoweredSimple.h"
    

    我们也可以在 C++ 代码中使用 import 而不是 include,但他们可能使用 include 只是为了强调它是 C++ 代码。查看SuperpoweredBandpassFilterbank.h,我们看到SuperpoweredBandpassFilterbank 是一个C++ 类。 SuperpoweredObjective-C++ 类在Superpowered.mm 中使用它,参见filters 成员,它是一个指向SuperpoweredBandpassFilterbank 对象的指针。

    在您尝试构建的项目中,我看到 Superpowered 接口在桥接头中声明的位置,但我没有看到实现。 #import SuperpoweredRecorder.h 失败是由于 SuperpoweredRecorder.h 是 C++ 标头。 #include 应该在您的 Objective-C++ (.mm) 文件中,它在桥接头中没有用,因为 Swift 无论如何都无法理解 C++。

    希望这会有所帮助。欢迎来到 C++ 的世界。

    【讨论】:

    • 经过一段时间并与 Superpowered 的 CTO 进行了一些交谈后,我已经理解了您在此处解释的所有内容,并找到了解决方案,我将在几分钟后发布。但是现在事情很清楚了,谢谢!
    【解决方案3】:

    您必须提供方法的原型,这让我有点惊讶。 我之前在我的 Swift 项目中使用了 Objective C 库,我只需要在我的桥接头中添加头文件。

    请参阅我的项目中的示例。桥接头仅包含以下内容:

    //  Use this file to import your target's public headers that you would like to expose to Swift.
    //
    
    #import "QTouchposeApplication.h"
    #import <FBSDKCoreKit/FBSDKCoreKit.h>
    #import <FBSDKLoginKit/FBSDKLoginKit.h>
    #import <VungleSDK/VungleSDK.h>
    

    【讨论】:

    • 是的,我在使用 Objective-C 库时也没有问题,但在这里,库是用 C++ 编写的,这让设置起来更加痛苦。
    • 你是对的,我没有从你的原始帖子中得到这个,但看看@OmniProg 的答案现在是有道理的。感谢您发布您的解决方案!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-19
    • 2015-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-14
    相关资源
    最近更新 更多