Как использовать 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>