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?
3 Réponses :
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
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
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 } } }
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
actual typealias AtomicInt = AtomicInteger
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 }
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 }
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.