Как передать байты из Swift (iOS) в общий модуль Kotlin? - PullRequest
1 голос
/ 04 апреля 2019

Чтобы поделиться реализацией протокола между android и iOS-приложением, я экспериментирую с Kotlin Multiplatform.Я настроил базовый мультиплатформенный проект, как описано здесь .

Он определяет общий код в общем модуле ...

fun createApplicationScreenMessage() : String {
  return "Kotlin Rocks on ${platformName()}"
}

... который можно использоватьв проекте iOS CommonKt.createApplicationScreenMessage()

Теперь я хотел бы выполнить операции ввода-вывода в общем модуле.Я нашел Kotlinx-io для этого и могу использовать его внутри общего модуля.

Но как правильно спроектировать API между кодом Kotlin и кодом Swift, чтобы я мог передать InputStream / ByteArray/ ByteReadPacket эквивалентен из Swift в модуль kotlin?

например, что-то вроде этого с типами kotlinx-io, такими как ByteReadPacket:

Общий модуль Kotlin:

class ProtocolReader{
    public fun parse(packet: ByteArray): ParsedMessage {
    //parse data
    } 
}

Приложение Swift для iOS

var byteArray = [UInt8](characteristicData)
let reader = ProtocolReader()
reader.parse(byteArray)

Этот пример не работает, поскольку swift byteArray не совместим с KotlinByteArray.

Как мне этого добиться?Нужно ли мне определять конечные точки API для каждой платформы, например, в этом случае в модуле ios мультиплатформенного проекта Kotlin?или есть вспомогательные методы для создания типов данных kotlinx-io из типов данных ios?

1 Ответ

3 голосов
/ 05 апреля 2019

Все, что вы передаете в свой общий код, должно быть независимым от платформы, поэтому либо вы определяете модель, используя ожидаемый / фактический механизм , либо вы отображаете свои быстрые типы данных в типы данных kotlin.

Я не бегло говорю по-быстрому, но вы могли бы сделать что-то вроде этого:

let swiftByteArray : [UInt8] = []
let intArray : [Int8] = swiftByteArray
    .map { Int8(bitPattern: $0) }
let kotlinByteArray: KotlinByteArray = KotlinByteArray.init(size: Int32(swiftByteArray.count))
for (index, element) in intArray.enumerated() {
    kotlinByteArray.set(index: Int32(index), value: element)
}

Иногда полезно посмотреть на сгенерированные заголовки совместимости.

KotlinByte:

__attribute__((objc_runtime_name("KotlinByte")))
__attribute__((swift_name("KotlinByte")))
@interface MainByte : MainNumber
- (instancetype)initWithChar:(char)value;
+ (instancetype)numberWithChar:(char)value;
@end;

KotlinByteArray:

__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("KotlinByteArray")))
@interface MainKotlinByteArray : KotlinBase
+ (instancetype)arrayWithSize:(int32_t)size 
__attribute__((swift_name("init(size:)")));
+ (instancetype)arrayWithSize:(int32_t)size init:(MainByte *(^)(MainInt *))init 
__attribute__((swift_name("init(size:init:)")));
+ (instancetype)alloc __attribute__((unavailable));
+ (instancetype)allocWithZone:(struct _NSZone *)zone. __attribute__((unavailable));
- (int8_t)getIndex:(int32_t)index __attribute__((swift_name("get(index:)")));
- (MainKotlinByteIterator *)iterator __attribute__((swift_name("iterator()")));
- (void)setIndex:(int32_t)index value:(int8_t)value 
__attribute__((swift_name("set(index:value:)")));
@property (readonly) int32_t size;
@end;
...