Доступ к стандартной библиотеке Kotlin из Swift - PullRequest
0 голосов
/ 01 ноября 2018

В моем проекте Kotlin Multiplatform я пытаюсь получить доступ к типам Kotlin, определенным в kotlin-stdlib, из Swift.

TL; DR : Типы / методы StdLib, по-видимому, не приводят к определениям заголовков, я хотел бы решение, которое не включает в себя написание большого количества шаблонного кода

Мой сценарий

У меня есть интерфейс, определенный в Kotlin ...

interface MyKotlinInterface {
  fun run() : Sequence<String>
}

... и реализовал этот интерфейс в Swift ...

class MySwiftClass : MyKotlinInterface {
  func run() -> KotlinSequence {
    // return sequenceOf("foo")
  }
}

... там я пытаюсь создать Sequence, но нет доступных методов из пакета kotlin.sequences (например, generateSequence).

Возможно ли на самом деле получить доступ к типам или методам фреймворка Kotlin помимо того, что я определяю в своем коде - если да, то как? Кроме того, как этого можно достичь без написания стандартного кода?

Подробнее

Взглянув на сгенерированный заголовочный файл Objective-C, я вижу определения для моего класса (очевидно) и базовых типов Kotlin. Чего не хватает, так это практически всего из стандартной функциональности библиотеки (я забочусь обо всем, что связано с Sequence).

Мой build.gradle.kts выглядит так:

plugins {
  kotlin("multiplatform") version "1.3.0"
}

kotlin {
    targets { /* ... */ }

    sourceSets {

        getByName("commonMain") {
            dependencies {
                api("org.jetbrains.kotlin:kotlin-stdlib-common")
            }
        }

        // ...

        getByName("iosMain") {
            dependencies {
                api("org.jetbrains.kotlin:kotlin-stdlib")
            }
        }
    }
}

Определив kotlin-stdlib как зависимость для цели iOS, я бы ожидал, что они станут доступны из Swift.

Минимальный рабочий пример

https://github.com/panzerfahrer/so-mwe-kotlin-mpp-swift

Текущий подход к решению

Единственное решение, которое я придумал, это написание нужной функции для цели iOS:

fun <T : kotlin.Any> generateSequence(nextFunction: () -> T?): kotlin.sequences.Sequence<T> = kotlin.sequences.generateSequence(nextFunction)

Это работает в порядке , но крайне неудовлетворительно, так как требует большого количества стандартного кода. Кроме того, функции расширения не могут быть сделаны доступными таким способом и потребуют большего количества стандартного кода или даже переписывания частей стандартной библиотеки.

Желаемое решение

Мне нравится, чтобы как можно больше не писать шаблонный код. Что меня действительно волнует, так это наличие (в моем случае) Sequence полностью доступного из Swift. Мне кажется, было бы достаточно, чтобы компилятор генерировал выбранные или все определения заголовков для стандартной функциональности библиотеки.

1 Ответ

0 голосов
/ 15 февраля 2019

Вам действительно нужны ленивые вычисления (иначе Sequence) в вашем коде Kotlin? Если нет, я бы порекомендовал вместо этого использовать List<T> (и он отображается на Swift напрямую).

Для реализации Sequence обходным путем может быть экспорт фабричной функции из вашей библиотеки Kotlin, например, Вы можете объявить функцию как

fun <T : kotlin.Any> generateSequence(nextFunction: () -> T?)
    = kotlin.sequences.generateSequence(nextFunction)

Вы можете выбрать любую другую заводскую функцию для Sequence, которая соответствует вашему сценарию использования.

В общем, в стандартной библиотеке Kotlin слишком много функций. Экспорт их всех в Swift создаст слишком много бесполезных символов в двоичном файле и увеличит время компиляции.

...