如何在Swift项目中使用超动力库

时间:2022-09-07 08:25:56

I want to make an app in Swift that simply record via the mic of the iPhone and then play the sound recorded.

我想做一个Swift的应用,通过iPhone的麦克风记录,然后播放录制的声音。

For that, I'd like to use the lib Superpowered that is a static library with header files.

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

For that, I tried to drag and drop the .a and headers files in my project (Xcode create for me a bridging header file), add the .a in "Linked Frameworks and Libraries" in Xcode > Target > General (and so in Xcode > Target > Build phases > "Link Binary With Libraries" too) and index the .h files path in Xcode > Target > Build Settings > Search Paths > Library Search Paths.

,我试着拖拽。和头文件在我的项目对我来说(Xcode创建桥接头文件),添加在“链接的框架和库”。在Xcode中目标> General >(所以在Xcode中> >构建阶段>目标”链接的二进制库”)和指数. h文件路径在Xcode中> > >构建目标设置搜索路径>库搜索路径。

But with that I have the error "ld: symbol(s) not found for architecture arm64" Exactly the same as here XCode: Undefined symbols for architecture arm64 error and I tried all the solutions that I found on the web for that, still no way to compile.

但是,我有一个错误的“ld:符号(s),没有找到架构arm64”和这里的XCode完全相同:架构arm64错误的未定义符号,我尝试了我在web上找到的所有解决方案,仍然没有办法编译。

SO !

如此!

Superpowered gives us a sample app to show how to mix Objective-C++ and use their lib within a Swift project (Here's a link to the git if you want https://github.com/superpoweredSDK/Low-Latency-Android-Audio-iOS-Audio-Engine).

superpower为我们提供了一个示例应用程序,演示如何在一个Swift项目中混合Objective-C+和使用它们的lib(如果您想要https://github.com/superpoweredsdk/low - android - audio - ios-audio - engine)。

Here is some screenshots of the sample project with what I understand and what I don't :

以下是一些我理解和不理解的示例项目的截屏:

如何在Swift项目中使用超动力库

The Bridging-Header-File with the prototypes of the methods of the lib that I want to use within my Swift code (I don't like this but if it's the only way...).

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

如何在Swift项目中使用超动力库

The viewController file where the code in Swift is, and where I can create a Superpowered object thank's to the Bridging-Header-File, and call the methods that I've put in it.

视图控制器文件,其中的代码在Swift中,我可以创建一个超动力对象感谢桥头文件,并调用我放入其中的方法。

如何在Swift项目中使用超动力库

And wtf I don't even understand why this Objective-C++ file is here and what it contains. It comes out from nowhere, not even their lib files.

我甚至不明白为什么这个objective - c++文件在这里,它包含什么。它无处不在,甚至连他们的库文件都没有。

So with this sample project in mind, I've created my own project, here is some screenshots :

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

如何在Swift项目中使用超动力库

The same Bridging-Header-File that in the sample project except that I include SuperpoweredIOSAudioIO.h so I can use SuperpoweredIOSAudioIODelegate.

在示例项目中,除了包含SuperpoweredIOSAudioIO之外,与此相同的连接头文件。所以我可以使用超级powerediosaudioiodelegate。

如何在Swift项目中使用超动力库

My viewController file where the code in Swift is, and where I can create a Superpowered object thank's to the Bridging-Header-File, and call the methods that I've put in it.

我的viewController文件,在Swift的代码中,我可以创建一个超动力的对象感谢到bridger - header - file,并调用我放入的方法。

Until here, it's great, except that I can't for exemple create a SuperpoweredRecorder object. If I try to include the SuperpoweredRecorder.h file in my Bridging-Header-File I have these errors :

直到这里,它还是很棒的,只是我不能创建一个SuperpoweredRecorder对象。如果我试着包括超功率记录仪。h文件在我的连接头文件我有这些错误:

如何在Swift项目中使用超动力库

So I saw that it is because SuperpoweredRecorder.h includes some .cpp files and I have to create a wrapper for cpp (a little bit like I did with the bridging header, no ?) but that includes a .h and a .mm file and I don't know what I have to put in that .mm file (the code of SuperpoweredRecorder.cpp ? But I don't have access to it)

我看到这是因为超级录音机。h包括一些. cpp文件,我需要创建一个包装器cpp(有点像我的连接头,不是吗?),但包括. h和功能文件,我不知道我要把功能文件(SuperpoweredRecorder的代码。cpp吗?但是我没有权限)

So yes, I'm a little bit confused with all that stuff, can you help me to understand how can I use all the Superpowered lib in my Swift project please ?

是的,我有点搞不懂这些东西,你能帮我理解我如何在我的Swift项目中使用所有的超动力库吗?

3 个解决方案

#1


5  

As I said in comment to @OmniProg, I had a little conversation with the CTO of Superpowered that helped me a lot to find the solution below.

正如我在对@OmniProg的评论中所说的,我与superpower的CTO进行了一次简短的交谈,这帮助我找到了下面的解决方案。

So, as Swift cannot interact directly with C++ but can with Objective-C, I had to create objects in Objective-C++ (.mm file, a mix between C++ and Objective-C) that wrap C++ classes of the lib Superpowered.

因此,由于Swift不能直接与c++交互,但是可以使用Objective-C,我必须在objective - c++中创建对象。mm文件,c++和Objective-C)的混合文件,封装了lib超功能的c++类。

Here is an example with the SuperpoweredRecorder object from the lib :

下面是来自lib的SuperpoweredRecorder对象的一个例子:

如何在Swift项目中使用超动力库

Here I create a .h file where I prototype my wrapper with the name SuperpoweredRecorderWrapped, and I also prototype in it all the methods of the SuperpoweredRecorder of the lib that I want to use.

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

如何在Swift项目中使用超动力库

Then I create a new .m file that I rename .mm and I implement SuperpoweredRecorderWrapped on it. I import both SuperpoweredRecorderWrapped.h and SuperpoweredRecorder.h. I create a SuperpoweredRecorder object as property named _wrapped and in my methods, I call the corresponding method of the _wrapped object. With that, when I'll call start of a SuperpoweredRecorderWrapped in my Swift code, this one will call start of _wrapped, a SuperpoweredRecorder object. See the trick ?

然后,我创建一个新的.m文件,并将其重命名为.mm,并在其上实现superpoweredrecorderpackaging。我两SuperpoweredRecorderWrapped进口。h和SuperpoweredRecorder.h。我将一个SuperpoweredRecorder对象创建为名为_wrap的属性,在我的方法中,我调用_wrap对象的相应方法。这样,当我调用包装在我的Swift代码中的superpoweredrecorderstart时,这个将调用_wrap的start,一个SuperpoweredRecorder对象。看到的诀窍吗?

如何在Swift项目中使用超动力库

And finally I include all the wrapped classes in my Bridging-Header, like that I can instantiate my wrapped objects from Swift.

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

NOTE: All the C++ code HAVE to be in .mm files, that's why I make my #include of .h that contains C++ code in my .mm file and not in my .h file.

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

#2


3  

I haven't programmed in Objective-C++, but I do have experience with C, C++, Objective-C, and Swift, so here are some observations and ideas based on looking at the Superpowered SDK and sample code.

我还没有在Objective-C+中编写过程序,但是我有使用C、c++、Objective-C和Swift的经验,所以这里有一些观察和想法,它们基于超级SDK和示例代码。

A bridging header lets Swift interface directly with Objective-C, and since Objective-C is a strict superset of C, this implies interfacing with C as well. However, you cannot interface directly with C++, and that's where Objective-C++ comes to the rescue. From what I'm seeing you can mix Objective-C and C++ code in Objective-C++, which allows Objective-C to use C++ classes.

桥接头允许Swift直接与Objective-C接口,而且由于Objective-C是C的严格超集,这也意味着与C接口。但是,您不能直接与c++交互,这就是objective - c++的解决方案。在我看来,您可以在objective - c++中混合Objective-C和c++代码,这允许Objective-C使用c++类。

Now on to some specifics.

现在来看一些细节。

The bridging header in the SuperpoweredFrequencies example that you looked at introduces a new Objective-C class, Superpowered, which is not part of the library, but of the example, and is implemented in Superpowered.mm. It is an Objective-C++ file, because Superpowered calls some C++ code.

您看到的superpoweredfrequency示例中的桥接头引入了一个新的Objective-C类superpower,它不是库的一部分,而是示例的一部分,是在superpower .mm中实现的。它是一个objective - c++文件,因为superpower调用了一些c++代码。

Looking at Superpowered.mm, you will see that it imports Objective-C headers:

看着超。你会看到它导入Objective-C标题:

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

as well as C and C++ headers:

以及C和c++ header:

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

We could have used import instead of include for C++ code, too, but they are probably using include just to emphasize that it is C++ code. Looking at SuperpoweredBandpassFilterbank.h, we see that SuperpoweredBandpassFilterbank is a C++ class. It is used in Superpowered.mm by the Superpowered Objective-C++ class, see the filters member, which is a pointer to a SuperpoweredBandpassFilterbank object.

我们也可以使用import而不是include来表示c++代码,但是他们可能使用include只是为了强调它是c++代码。看着SuperpoweredBandpassFilterbank。我们看到SuperpoweredBandpassFilterbank是一个c++类。它用于超动力。通过超能力的objective - c++类,请参见过滤器成员,它是指向超级poweredbandpassfilterbank对象的指针。

In the project you attempted to build, I see where the Superpowered interface is declared in the bridging header, but I don't see an implementation. The failure to #import SuperpoweredRecorder.h is due to SuperpoweredRecorder.h being a C++ header. The #include should be in your Objective-C++ (.mm) file, it's useless in the bridging header, since Swift can't make sense of C++ anyhow.

在您试图构建的项目中,我看到了超级界面在桥接头中声明的位置,但是我没有看到实现。导入SuperpoweredRecorder的失败。h是由SuperpoweredRecorder发明的。h是一个c++头。#include应该在您的objective - c++ (.mm)文件中,在桥接头中没有用处,因为Swift无论如何都不能理解c++。

Hopefully this is helpful. Welcome to the world of C++.

希望这是有帮助的。欢迎来到c++的世界。

#3


0  

I'm a bit surprised that you would have to provide prototypes of method. I used Objective C libraries in my Swift project before and I only had to add the header files in my bridging header.

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

See example from my project. The bridging header contains just that:

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

//  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>

#1


5  

As I said in comment to @OmniProg, I had a little conversation with the CTO of Superpowered that helped me a lot to find the solution below.

正如我在对@OmniProg的评论中所说的,我与superpower的CTO进行了一次简短的交谈,这帮助我找到了下面的解决方案。

So, as Swift cannot interact directly with C++ but can with Objective-C, I had to create objects in Objective-C++ (.mm file, a mix between C++ and Objective-C) that wrap C++ classes of the lib Superpowered.

因此,由于Swift不能直接与c++交互,但是可以使用Objective-C,我必须在objective - c++中创建对象。mm文件,c++和Objective-C)的混合文件,封装了lib超功能的c++类。

Here is an example with the SuperpoweredRecorder object from the lib :

下面是来自lib的SuperpoweredRecorder对象的一个例子:

如何在Swift项目中使用超动力库

Here I create a .h file where I prototype my wrapper with the name SuperpoweredRecorderWrapped, and I also prototype in it all the methods of the SuperpoweredRecorder of the lib that I want to use.

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

如何在Swift项目中使用超动力库

Then I create a new .m file that I rename .mm and I implement SuperpoweredRecorderWrapped on it. I import both SuperpoweredRecorderWrapped.h and SuperpoweredRecorder.h. I create a SuperpoweredRecorder object as property named _wrapped and in my methods, I call the corresponding method of the _wrapped object. With that, when I'll call start of a SuperpoweredRecorderWrapped in my Swift code, this one will call start of _wrapped, a SuperpoweredRecorder object. See the trick ?

然后,我创建一个新的.m文件,并将其重命名为.mm,并在其上实现superpoweredrecorderpackaging。我两SuperpoweredRecorderWrapped进口。h和SuperpoweredRecorder.h。我将一个SuperpoweredRecorder对象创建为名为_wrap的属性,在我的方法中,我调用_wrap对象的相应方法。这样,当我调用包装在我的Swift代码中的superpoweredrecorderstart时,这个将调用_wrap的start,一个SuperpoweredRecorder对象。看到的诀窍吗?

如何在Swift项目中使用超动力库

And finally I include all the wrapped classes in my Bridging-Header, like that I can instantiate my wrapped objects from Swift.

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

NOTE: All the C++ code HAVE to be in .mm files, that's why I make my #include of .h that contains C++ code in my .mm file and not in my .h file.

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

#2


3  

I haven't programmed in Objective-C++, but I do have experience with C, C++, Objective-C, and Swift, so here are some observations and ideas based on looking at the Superpowered SDK and sample code.

我还没有在Objective-C+中编写过程序,但是我有使用C、c++、Objective-C和Swift的经验,所以这里有一些观察和想法,它们基于超级SDK和示例代码。

A bridging header lets Swift interface directly with Objective-C, and since Objective-C is a strict superset of C, this implies interfacing with C as well. However, you cannot interface directly with C++, and that's where Objective-C++ comes to the rescue. From what I'm seeing you can mix Objective-C and C++ code in Objective-C++, which allows Objective-C to use C++ classes.

桥接头允许Swift直接与Objective-C接口,而且由于Objective-C是C的严格超集,这也意味着与C接口。但是,您不能直接与c++交互,这就是objective - c++的解决方案。在我看来,您可以在objective - c++中混合Objective-C和c++代码,这允许Objective-C使用c++类。

Now on to some specifics.

现在来看一些细节。

The bridging header in the SuperpoweredFrequencies example that you looked at introduces a new Objective-C class, Superpowered, which is not part of the library, but of the example, and is implemented in Superpowered.mm. It is an Objective-C++ file, because Superpowered calls some C++ code.

您看到的superpoweredfrequency示例中的桥接头引入了一个新的Objective-C类superpower,它不是库的一部分,而是示例的一部分,是在superpower .mm中实现的。它是一个objective - c++文件,因为superpower调用了一些c++代码。

Looking at Superpowered.mm, you will see that it imports Objective-C headers:

看着超。你会看到它导入Objective-C标题:

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

as well as C and C++ headers:

以及C和c++ header:

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

We could have used import instead of include for C++ code, too, but they are probably using include just to emphasize that it is C++ code. Looking at SuperpoweredBandpassFilterbank.h, we see that SuperpoweredBandpassFilterbank is a C++ class. It is used in Superpowered.mm by the Superpowered Objective-C++ class, see the filters member, which is a pointer to a SuperpoweredBandpassFilterbank object.

我们也可以使用import而不是include来表示c++代码,但是他们可能使用include只是为了强调它是c++代码。看着SuperpoweredBandpassFilterbank。我们看到SuperpoweredBandpassFilterbank是一个c++类。它用于超动力。通过超能力的objective - c++类,请参见过滤器成员,它是指向超级poweredbandpassfilterbank对象的指针。

In the project you attempted to build, I see where the Superpowered interface is declared in the bridging header, but I don't see an implementation. The failure to #import SuperpoweredRecorder.h is due to SuperpoweredRecorder.h being a C++ header. The #include should be in your Objective-C++ (.mm) file, it's useless in the bridging header, since Swift can't make sense of C++ anyhow.

在您试图构建的项目中,我看到了超级界面在桥接头中声明的位置,但是我没有看到实现。导入SuperpoweredRecorder的失败。h是由SuperpoweredRecorder发明的。h是一个c++头。#include应该在您的objective - c++ (.mm)文件中,在桥接头中没有用处,因为Swift无论如何都不能理解c++。

Hopefully this is helpful. Welcome to the world of C++.

希望这是有帮助的。欢迎来到c++的世界。

#3


0  

I'm a bit surprised that you would have to provide prototypes of method. I used Objective C libraries in my Swift project before and I only had to add the header files in my bridging header.

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

See example from my project. The bridging header contains just that:

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

//  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>