Как использовать Superpowered lib в проекте Swift

Я хочу сделать приложение в Swift, которое просто записывается через микрофон iPhone, а затем воспроизводит записанный звук.

Для этого я хотел бы использовать lib Superpowered, статичную библиотеку с файлами заголовков.

Для этого я попытался перетащить файлы .a и headers в свой проект (Xcode создает для меня заголовочный файл моста), добавьте .a в "Связанные структуры и библиотеки" в Xcode > Target > General ( и т.д. в Xcode > Target > Build phase > "Link Binary With Libraries" ) и индексируйте путь .h файлов в Xcode > Target > Build Settings > Path Search > Path Search >

Но с этим я имею ошибку "ld: символ (ы), не найденный для архитектуры arm64" Точно так же, как здесь XCode: Undefined символы для архитектуры arm64 error, и я пробовал все решения, которые я нашел в Интернете для этого, но до сих пор не удалось скомпилировать.

SO!

Superpowered дает нам пример приложения, чтобы показать, как смешивать Objective-C ++ и использовать их lib в проекте Swift (здесь ссылка на git, если вы хотите https://github.com/superpoweredSDK/Low-Latency-Android-Audio-iOS-Audio-Engine).

Вот несколько скриншотов примерного проекта с тем, что я понимаю, а что нет:

Модифицировать заголовочный файл Superpowered

Файл Bridging-Header-File с прототипами методов lib, которые я хочу использовать в моем коде Swift (мне это не нравится, но если это единственный способ...).

Файл ViewController

Файл viewController, где находится код в Swift, и где я могу создать объект Superpowered благодаря файлу Bridging-Header-File и вызвать методы, которые я в него вложил.

. mm file

И wtf Я даже не понимаю, почему этот Objective-C ++ файл здесь и что он содержит. Он выходит из ниоткуда, даже файлы lib.

Итак, с учетом этого примера проекта, я создал свой собственный проект, вот несколько скриншотов:

Briging-Header-File

Тот же файл-заголовок-заголовок, который в примере проекта, за исключением того, что я включаю SuperpoweredIOSAudioIO.h, поэтому я могу использовать SuperpoweredIOSAudioIODelegate.

viewController

Мой файл viewController, где находится код в Swift, и где я могу создать объект Superpowered благодаря файлу Bridging-Header-File и вызвать методы, которые я вложил в него.

До сих пор это здорово, за исключением того, что я не могу создать объект SuperpoweredRecorder. Если я попытаюсь включить файл SuperpoweredRecorder.h в мой файл-заголовок-заголовок, у меня есть следующие ошибки:

errors

Итак, я понял, что это связано с тем, что SuperpoweredRecorder.h содержит некоторые .cpp файлы, и мне нужно создать оболочку для cpp (немного похож на заголовок моста, нет?), но это включает в себя .h и .mm file, и я не знаю, что мне нужно добавить в файл .mm(код SuperpoweredRecorder.cpp? Но у меня нет доступа к нему)

Итак, да, я немного смущен всем этим, не могли бы вы помочь мне понять, как я могу использовать всю супермощную lib в моем проекте Swift?

Ответ 1

Как я уже сказал в комментарии к @OmniProg, у меня был небольшой разговор с техническим директором Superpowered, который помог мне найти решение ниже.

Итак, поскольку Swift не может напрямую взаимодействовать с С++, но может с Objective-C, мне пришлось создавать объекты в Objective-C ++ (.mm файл, сочетание между С++ и Objective-C), которые переносят классы С++ lib Superpowered.

Вот пример с объектом SuperpoweredRecorder из lib:

SuperpoweredRecorderWrapped.h

Здесь я создаю файл .h, где я прототип своего обертки с именем SuperpoweredRecorderWrapped, и я также прототип в нем всех методов SuperpoweredRecorder lib, которые я хочу использовать.

SuperpoweredRecorderWrapped.mm

Затем я создаю новый .m файл, который я переименовал .mm, и я реализую SuperpoweredRecorderWrapped на нем. Я импортирую как SuperpoweredRecorderWrapped.h, так и SuperpoweredRecorder.h. Я создаю объект SuperpoweredRecorder как свойство с именем _wrapped, и в своих методах я вызываю соответствующий метод объекта _wrapped. При этом, когда я назову start для SuperpoweredRecorderWrapped в моем коде Swift, этот вызов вызовет start объекта _wrapped, SuperpoweredRecorder. См. Трюк?

Bridge-Header

И, наконец, я включаю все завернутые классы в свой заголовок Bridging-Header, так что я могу создать экземпляр моих обернутых объектов из Swift.

ПРИМЕЧАНИЕ: весь код на С++ должен быть в .mm файлах, поэтому я делаю свой #include из .h, который содержит код на С++ в моем файле .mm, а не в моем .h файл.

Ответ 2

Я не запрограммировал в Objective-C ++, но у меня есть опыт работы с C, С++, Objective-C и Swift, так что вот некоторые замечания и идеи, основанные на просмотре Superpowered SDK и пример кода.

Заголовок моста позволяет прямому интерфейсу Swift с помощью Objective-C, а поскольку Objective-C является строгим надмножеством C, это подразумевает сопряжение с C. Однако вы не можете напрямую взаимодействовать с С++ и что там, где Objective-C ++ приходит на помощь. Из того, что я вижу, вы можете смешивать Objective-C и код С++ в Objective-C ++, что позволяет Objective-C использовать классы С++.

Теперь о некоторых особенностях.

В заголовке "SuperpoweredFrequencies", который вы рассмотрели, заголовок моста вводит новый класс Objective-C, Superpowered, который не является частью библиотеки, а примера и реализован в Superpowered.mm. Это файл Objective-C ++, потому что Superpowered вызывает некоторый код на С++.

Глядя на Superpowered.mm, вы увидите, что он импортирует заголовки Objective-C:

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

а также заголовки C и С++:

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

Мы могли бы использовать import вместо include для кода С++, но они, вероятно, используют include, чтобы подчеркнуть, что это код на С++. Рассматривая SuperpoweredBandpassFilterbank.h, мы видим, что SuperpoweredBandpassFilterbank является классом С++. Он используется в Superpowered.mm классом Superpowered Objective-C ++, см. Член filters, который является указателем на объект SuperpoweredBandpassFilterbank.

В проекте, который вы пытались построить, я вижу, где интерфейс Superpowered объявлен в заголовке моста, но я не вижу реализации. Ошибка #import SuperpoweredRecorder.h связана с тем, что SuperpoweredRecorder.h является заголовком С++. #include должен быть в вашем файле Objective-C ++ (.mm), он бесполезен в заголовочном заголовке, так как Swift вообще не имеет смысла в С++.

Надеюсь, это поможет. Добро пожаловать в мир С++.

Ответ 3

Я немного удивлен, что вам придется предоставить прототипы метода. Раньше я использовал библиотеки Objective C в моем проекте Swift, и мне приходилось добавлять файлы заголовков в свой заголовок моста.

См. пример из моего проекта. Заголовок моста содержит только это:

//  Use this file to import your target 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>