如何在 Swift 项目中使用 Superpowered 库

How to use Superpowered lib in Swift project

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

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

为此,我尝试将 .a 和头文件拖放到我的项目中(Xcode 为我创建一个桥接头文件),将 "Linked Frameworks and Libraries" 中的 .a 添加到 Xcode > Target > General(在 Xcode > Target > Build phases > "Link Binary With Libraries" 中也是如此)并在 Xcode > Target > Build Settings > Search 中索引 .h 文件路径路径 > 库搜索路径。

但是我有错误 "ld: symbol(s) not found for architecture arm64" 和这里一模一样XCode: Undefined symbols for architecture arm64 error,网上找的所有解决办法都试过了,还是编译不出来

所以!

Superpowered 给了我们一个示例应用程序来展示如何混合 Objective-C++ 并在 Swift 项目中使用他们的库(这里是 link 到 git如果你想要 https://github.com/superpoweredSDK/Low-Latency-Android-Audio-iOS-Audio-Engine).

以下是示例项目的一些屏幕截图,其中包含我了解的内容和不了解的内容:

带有我想在我的 Swift 代码中使用的库方法原型的桥接头文件(我不喜欢这个,但如果这是唯一的方法...) .

viewController 文件,其中包含 Swift 中的代码,我可以在其中创建一个超级对象,这要归功于 Bridging-Header-File,并调用我放入的方法它。

而且我什至不明白为什么这个 Objective-C++ 文件在这里以及它包含什么。它不知从何而来,甚至不是他们的 lib 文件。

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

与示例项目中相同的桥接头文件,除了我包含 SuperpoweredIOSAudioIO.h 以便我可以使用 SuperpoweredIOSAudioIODelegate.

我的 viewController 文件,其中包含 Swift 中的代码,我可以在其中创建一个 Superpowered 对象,这要归功于 Bridging-Header-File,并调用我放入的方法它。

到这里为止,一切都很棒,只是我无法创建一个 SuperpoweredRecorder 对象。如果我尝试在我的 Bridging-Header-File 中包含 SuperpoweredRecorder.h 文件,我会遇到这些错误:

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

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

我有点惊讶你必须提供方法原型。 我之前在我的 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、C++、Objective-C 和 Swift 的经验,所以这里有一些基于观察和想法查看 Superpowered SDK 和示例代码。

桥接 header 让 Swift 直接与 Objective-C 接口,并且由于 Objective-C 是 C 的严格超集,这也意味着与 C 接口。但是,您不能直接与 C++ 交互,这就是 Objective-C++ 的用武之地。据我所见,您可以在 Objective-C++ 中混合使用 Objective-C 和 C++ 代码,这允许 Objective-C 使用 C++ classes.

现在谈谈一些细节。

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

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

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

以及 C 和 C++ headers:

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

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

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

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

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

因此,由于 Swift 不能直接与 C++ 交互但可以与 Objective-C 交互,我不得不在 Objective-C++ 中创建对象(.mm 文件,C++ 和Objective-C) 封装了 Superpowered 库的 C++ 类。

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

在这里,我创建了一个 .h 文件,我在其中使用名称 SuperpoweredRecorderWrapped 对我的包装器进行了原型设计,并且还在其中对我想使用的库的 SuperpoweredRecorder 的所有方法进行了原型设计.

然后我创建一个新的 .m 文件,我将其重命名为 .mm 并在其上实施 SuperpoweredRecorderWrapped。 我导入了 SuperpoweredRecorderWrapped.hSuperpoweredRecorder.h。 我创建了一个名为 _wrapped 的 属性 对象,并在我的方法中调用了 _wrapped 对象的相应方法。 这样,当我在 Swift 代码中调用 SuperpoweredRecorderWrappedstart 时,这个代码将调用 _wrappedstartSuperpoweredRecorder 目的。看到技巧了吗?

最后我将所有包装的 类 包含在我的 Bridging-Header 中,这样我就可以从 Swift.

实例化我的包装对象

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