3
votes

Kotlin Multiplatform: partage de l'implémentation de classe réelle pour plusieurs cibles (iOS, macOS)

Je travaille sur un projet Kotlin / Native Multiplatform qui prend en charge JVM, iOS et macOS. Ma configuration comporte les modules suivants:

- common
- ios
- jvm
- macos

Je souhaite utiliser du code natif comme classe réelle et mettre une classe attendue dans commun . Cependant, l'implémentation de classe réelle est identique pour plusieurs cibles (iOS et macOS). Y a-t-il un moyen de configurer mes sources (peut-être dans Gradle) pour ne pas avoir à conserver 2 copies identiques de la classe réelle?


2 commentaires

Pouvez-vous développer ce "Cependant, l'implémentation de classe réelle est identique pour chaque cible (iOS, JVM et MacOS)". S'ils sont identiques, pourquoi faites-vous des attentes / réelles? Je peux voir qu'iOS et MacOS sont identiques, mais les trois?


@KevinGalligan édité avec clarification. Vous avez raison, iOS et macOS sont les mêmes mais JVM est différent.


3 Réponses :


0
votes

Si les trois implémentations sont identiques, mettez simplement ce code dans common . expect / actual n'est utilisé que pour des éléments différents sur différentes plates-formes


1 commentaires

Au départ, je me suis mal exprimé. Je voulais dire que les implémentations cibles iOS et macOS sont identiques. JVM est différent. Je souhaite utiliser un entier atomique que je peux utiliser AtomicInt pour iOS et macOS mais doit utiliser AtomicInteger pour JVM



2
votes

Dans Okio , nous déclarons deux ensembles de sources supplémentaires, nativeMain et nativeTest et configurez les ensembles de sources natifs intégrés pour en dépendre:

apply plugin: 'org.jetbrains.kotlin.multiplatform'

kotlin {
  iosX64()
  iosArm64()
  linuxX64()
  macosX64()
  mingwX64('winX64')
  sourceSets {
    nativeMain {
      dependsOn commonMain
    }
    nativeTest {
      dependsOn commonTest
    }

    configure([iosX64Main, iosArm64Main, linuxX64Main, macosX64Main, winX64Main]) {
      dependsOn nativeMain
    }
    configure([iosX64Test, iosArm64Test, linuxX64Test, macosX64Test, winX64Test]) {
      dependsOn nativeTest
    }
  }
}


0 commentaires

4
votes

Stately a une configuration assez complexe. iOS et Macos partagent tous le même code.

Pour structurer le projet, il y a commonMain , nativeCommonMain en dépend, et en fait appleMain qui dépend de nativeCommonMain.

actual class AtomicInt actual constructor(initialValue:Int){
  private val atom = AtomicInt(initialValue)

  actual fun get(): Int = atom.value

  actual fun set(newValue: Int) {
    atom.value = newValue
  }

  actual fun incrementAndGet(): Int = atom.addAndGet(1)

  actual fun decrementAndGet(): Int = atom.addAndGet(-1)

  actual fun addAndGet(delta: Int): Int = atom.addAndGet(delta)

  actual fun compareAndSet(expected: Int, new: Int): Boolean = atom.compareAndSet(expected, new)

}

Cette structure est probablement plus profonde que ce dont vous avez besoin, mais nous avions besoin de quelque chose pour Linux et Windows qui était différent. Je pense que la réponse d'Egor ci-dessus est plus facile à suivre.

Nous définissons en fait les atomes multiplateformes dans Stately, vous pouvez donc les utiliser comme source d'inspiration ou simplement utiliser la bibliothèque elle-même.

https://github.com/touchlab/Stately

Commun

actual typealias AtomicInt = AtomicInteger

JVM

expect class AtomicInt(initialValue: Int) {
  fun get(): Int
  fun set(newValue: Int)
  fun incrementAndGet(): Int
  fun decrementAndGet(): Int

  fun addAndGet(delta: Int): Int
  fun compareAndSet(expected: Int, new: Int): Boolean
}

Natif

commonMain {
    dependencies {
        implementation 'org.jetbrains.kotlin:kotlin-stdlib-common'
    }
}

jvmMain {
    dependsOn commonMain
    dependencies {
        implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
    }
}

nativeCommonMain {
    dependsOn commonMain
}

appleMain {
    dependsOn nativeCommonMain
}

configure([iosX64Main, iosArm64Main, macosMain, iosArm32Main]) {
    dependsOn appleMain
}


0 commentaires