Мультиплатформенная / нативная совместимость Kotlin с Objective-C framework

Я пытаюсь вызвать код Swift/Objective-C из Kotlin в мультиплатформенном проекте. Нет проблем с обращениями к коду платформы. Но когда я пытаюсь вызвать какую-то библиотеку (или фреймворк, не уверенный, как она правильно называется, так как я не разработчик iOS), это терпит неудачу. Документы утверждают, что можно вызвать код Objective-C и Swift, если он правильно экспортирован:

Kotlin / Native обеспечивает двунаправленную совместимость с Objective-C. Фреймворки и библиотеки Objective-C можно использовать в коде Kotlin, если они правильно импортированы в сборку (системные фреймы импортируются по умолчанию). Смотрите, например, "Использование cinterop" в документации плагина Gradle. Библиотека Swift может использоваться в коде Kotlin, если ее API экспортируется в Objective-C с помощью @objc. Модули Pure Swift пока не поддерживаются.

Но это ничего не говорит о том, как я могу импортировать их должным образом. Это только указывает на описание плагина gradle, которое описывает старую версию плагина gradle. Так что это не работает для меня. Наконец, я понял, что может быть способ импортировать код Objective C:

fromPreset(presets.iosX64, 'ios') {
        compilations.main.outputKinds('FRAMEWORK')
        compilations.main {
            cinterops {
                firebase {
                    def pods = '${System.getProperty("user.home")}/Projects/kmpp/iosApp/Pods/'
                    includeDirs '${pods}Firebase/CoreOnly/Sources',
                            '${pods}FirebaseAnalytics/Frameworks/FirebaseAnalytics.framework/Headers'
                }
            }
        }
    }

Сборка работает без сбоев, но ничего не импортирует. Что я делаю неправильно? Можно ли вообще импортировать такую ​​библиотеку?

UPD:

здесь я нашел пример использования cinterop инструмент как это:

cd samples/gitchurn
../../dist/bin/cinterop -def src/main/c_interop/libgit2.def \
 -compilerOpts -I/usr/local/include -o libgit2

Это выглядит как cinterop инструмент должен быть в /dist/bin/ папка в моих проектах, но такой папки нет. Где взять cinterop инструмент?

2 ответа

Решение

Я закончил с этим cinterops раздел в build.gradle

    fromPreset(presets.iosX64, 'ios') {
        // This preset is for iPhone emulator
        // Switch here to presets.iosArm64 (or iosArm32) to build library for iPhone device
        compilations.main {
            outputKinds('FRAMEWORK')
            cinterops {
                firebase {
                    defFile "$projectDir/src/iosMain/cinterop/firebase.def"
                    includeDirs {
                        allHeaders "$projectDir/../iosApp/Pods/FirebaseCore/Firebase/Core/Public",
                                   "$projectDir/../iosApp/Pods/FirebaseDatabase/Firebase/Database/Public"
                    }

                    compilerOpts "-F$projectDir/../iosApp/Pods/Firebase -F$projectDir/../iosApp/Pods/FirebaseCore -F$projectDir/../iosApp/Pods/FirebaseDatabase"
                    linkerOpts "-F$projectDir/../iosApp/Pods/Firebase -F$projectDir/../iosApp/Pods/FirebaseCore -F$projectDir/../iosApp/Pods/FirebaseDatabase"
                }
            }
        }
    }

конец это .def файл:

language = Objective-C
headers = FirebaseCore.h FirebaseDatabase.h

Что тут происходит? Каркасы кокоподов размещены в Pods каталог в вашем проекте xcode. Немного пройдясь по этой папке, вы найдете то, что вам нужно. Я не уверен, что есть какой-то стандарт, но Firebase разместить основной файл заголовка в Public папка. и он содержит ссылки на другие заголовочные файлы, которые ему нужны... Таким образом, вы указываете имена этих файлов в вашем .def файл в разделе заголовков.

Далее необходимо указать, где искать эти файлы и другие ссылки на них. Вы можете сделать это в .def файл в includeDirs или в build.gradle файл. Я предпочитаю файл build.gradle, так как он может использовать переменные. Таким образом, вы указываете путь к этим Public папки. (Этого достаточно для того, чтобы kotlin мог видеть API библиотеки, но чтобы запустить приложение, вам нужно скомпилировать и связать эту библиотеку...)

Компилятору и компоновщику нужно знать, где находится библиотека / фреймворк. Таким образом, вы указываете путь к корневой папке фреймворка в compilerOpts а также linkerOpts добавив к ним префикс -F если это рамки или -L если это библиотека.

Похоже, вы собираетесь использовать библиотеку cocoapods. В настоящее время плагин Gradle не поддерживает Cocapods из коробки. Но может быть зависимость от вашей библиотеки может быть настроена "вручную". Не могли бы вы поделиться ссылкой на ваш проект?

Другие вопросы по тегам