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

Я пытаюсь вызвать код Swift / Objective-C из Kotlin в многоплатформенном проекте. Нет проблем с обращениями к коду платформы. Но когда я пытаюсь вызвать какую-то библиотеку (или фреймворк, не уверенный, как она правильно называется, так как я не разработчик iOS), это терпит неудачу. Docs утверждает, что можно вызвать код 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 ]

0 голосов
/ 18 января 2019

Я закончил с этим 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

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

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

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

0 голосов
/ 03 января 2019

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

...