Spec-Zone.ru › Kotlin 1.6

Преобразование примитивных типов данных из C – учебник

В этом учебнике вы узнаете, какие типы данных C видны в Kotlin/Native и наоборот. Вы будете:

  • Узнавать Типы данных в языке C.

  • Создавать небольшую библиотеку на C, которая использует эти типы в экспортах.

  • Просматривать сгенерированные Kotlin API из библиотеки на C.

  • Выяснять, как Примитивные типы в Kotlin отображаются в C.

Типы в языке C

Какие типы существуют в языке C? Давайте возьмем статью типов данных C из Википедии в качестве основы. В языке программирования C существуют следующие типы:

  • базовые типы char, int, float, double с модификаторами signed, unsigned, short, long

  • структуры, объединения, массивы

  • указатели

  • указатели на функции

Также есть более специфические типы:

  • тип boolean (из C99)

  • size_t и ptrdiff_t (также ssize_t)

  • целочисленные типы с фиксированной шириной, такие как int32_t или uint64_t (из C99)

Также в языке C существуют следующие квалификаторы типов: const, volatile, restruct, atomic.

Лучший способ увидеть, какие типы данных C видны в Kotlin, — это попробовать.

Пример библиотеки на C

Создайте файл lib.h, чтобы увидеть, как функции на C отображаются в Kotlin:

#ifndef LIB2_H_INCLUDED
#define LIB2_H_INCLUDED

void ints(char c, short d, int e, long f);
void uints(unsigned char c, unsigned short d, unsigned int e, unsigned long f);
void doubles(float a, double b);

#endif

В файле отсутствует блок extern "C", который не нужен для этого примера, но может потребоваться, если вы используете C++ и перегруженные функции. В обсуждении совместимости с C++ на Stackoverflow содержатся дополнительные сведения об этом.

Для каждого набора файлов .h, вы будете использовать инструмент cinterop из Kotlin/Native для генерации Kotlin/Native библиотеки или .klib. Сгенерированная библиотека будет обеспечивать мосты для вызовов из Kotlin/Native в C. Она включает соответствующие Kotlin объявления для определений из файлов .h. Достаточно иметь только файл .h, чтобы запустить инструмент cinterop. И вам не нужно создавать файл lib.c, если вы не хотите скомпилировать и запустить пример. Более подробные сведения об этом содержатся на странице взаимодействия с C. Для учебника достаточно создать файл lib.def, содержащий следующее содержимое:

headers = lib.h

Вы можете включить все объявления непосредственно в файл .def после разделителя ---. Это может быть полезно для включения макросов или других определений C в код, генерируемый инструментом cinterop. Тела методов также компилируются и полностью включаются в исполняемый файл. Используйте эту функцию для получения работающего примера без необходимости компилятора C. Для реализации этого нужно добавить реализации функций C из файла lib.h, и поместить эти функции в файл .def. У вас будет следующий результат interop.def.

---

void ints(char c, short d, int e, long f) { }
void uints(unsigned char c, unsigned short d, unsigned int e, unsigned long f) { }
void doubles(float a, double b) { }

Файла interop.def достаточно для компиляции и запуска приложения или открытия его в IDE. Теперь настало время создать файлы проекта, открыть проект в IntelliJ IDEA и запустить его.

Проверка сгенерированных Kotlin API для библиотеки на C

Хотя можно использовать командную строку, либо напрямую, либо объединив ее со скрипт-файлом (например, с файлом .sh или .bat), этот подход не масштабируется для больших проектов с сотнями файлов и библиотек. В таких случаях лучше использовать компилятор Kotlin/Native с системой сборки, так как она помогает загрузить и кешировать бинарные файлы и библиотеки компилятора Kotlin/Native с транзитными зависимостями и запустить компилятор и тесты. Kotlin/Native может использовать систему сборки Gradle через плагин kotlin-multiplatform.

Основы настройки совместимого с IDE проекта с Gradle были рассмотрены в учебнике Базовое Kotlin/Native приложение. Пожалуйста, ознакомьтесь с ним, если вы ищете подробные начальные шаги и инструкции по началу нового Kotlin/Native проекта и его открытию в IntelliJ IDEA. В этом учебнике мы рассмотрим расширенные применения Kotlin/Native, связанные с взаимодействием с C, и сборки multiplatform с Gradle.

Сначала создайте папку проекта. Все пути в этом учебнике будут относительными к этой папке. Иногда недостающие каталоги необходимо создать перед добавлением новых файлов.

Используйте следующий файл сборки Gradle build.gradle(.kts):

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

repositories {
    mavenCentral()
}

kotlin {
  linuxX64("native") { // on Linux
  // macosX64("native") { // on x86_64 macOS
  // macosArm64("native") { // on Apple Silicon macOS
  // mingwX64("native") { // on Windows
    val main by compilations.getting
    val interop by main.cinterops.creating
    
    binaries {
      executable()
    }
  }
}

tasks.wrapper {
  gradleVersion = "6.7.1"
  distributionType = Wrapper.DistributionType.BIN
}
plugins {
    id 'org.jetbrains.kotlin.multiplatform' version '1.6.20'
}

repositories {
    mavenCentral()
}

kotlin {
  linuxX64('native') { // on Linux
  // macosX64("native") { // on x86_64 macOS
  // macosArm64("native") { // on Apple Silicon macOS
  // mingwX64('native') { // on Windows
    compilations.main.cinterops {
      interop 
    }
    
    binaries {
      executable()
    }
  }
}

wrapper {
  gradleVersion = '6.7.1'
  distributionType = 'BIN'
}

Файл проекта настраивает взаимодействие с C как дополнительный шаг сборки. Давайте переместим файл interop.def в каталог src/nativeInterop/cinterop. Gradle рекомендует использовать соглашения вместо конфигураций, например, файлы исходных кодов должны находиться в папке src/nativeMain/kotlin. По умолчанию все символы из C импортируются в пакет interop, возможно, вам захочется импортировать весь пакет в наши файлы .kt. Ознакомьтесь с документацией плагина kotlin-multiplatform, чтобы узнать обо всех различных способах его настройки.

Создайте файл-заглушку src/nativeMain/kotlin/hello.kt со следующим содержимым, чтобы увидеть, как объявления примитивных типов C видны из Kotlin:

import interop.*

fun main() {
  println("Hello Kotlin/Native!")
  
  ints(/* fix me*/)
  uints(/* fix me*/)
  doubles(/* fix me*/)
}

Теперь вы готовы открыть проект в IntelliJ IDEA и увидеть, как исправить пример проекта. Делая это, посмотрите, как примитивные типы C отображаются в Kotlin/Native.

Примитивные типы в Kotlin

С помощью IntelliJ IDEA's Перейти к | Объявление или ошибок компилятора, вы видите следующий сгенерированный API для функций C:

fun ints(c: Byte, d: Short, e: Int, f: Long)
fun uints(c: UByte, d: UShort, e: UInt, f: ULong)
fun doubles(a: Float, b: Double)

Типы C отображаются ожидаемым образом. Обратите внимание, что тип char отображается как kotlin.Byte, так как он обычно представляет собой 8-битовое знаковое значение.

C

Kotlin

char

kotlin.Byte

unsigned char

kotlin.UByte

short

kotlin.Short

unsigned short

kotlin.UShort

int

kotlin.Int

unsigned int

kotlin.UInt

long long

kotlin.Long

unsigned long long

kotlin.ULong

float

kotlin.Float

double

kotlin.Double

Исправление кода

Вы ознакомились со всеми определениями, и настало время исправить код. Запустите задачу Gradle runDebugExecutableNative в IDE или используйте следующую команду для запуска кода:

./gradlew runDebugExecutableNative

Конечный код в файле hello.kt может выглядеть так:

import interop.*

fun main() {
  println("Hello Kotlin/Native!")
  
  ints(1, 2, 3, 4)
  uints(5, 6, 7, 8)
  doubles(9.0f, 10.0)
}

Следующие шаги

Продолжайте изучать более сложные типы языка C и их представление в Kotlin/Native в следующих учебниках:

  • Преобразование структур и объединений из C

  • Преобразование указателей на функции из C

  • Преобразование строк из C

Документация по взаимодействию с C охватывает более сложные сценарии взаимодействия.

Последнее изменение: 07 апреля 2022
Взаимодействие с C Преобразование структур и объединений из C – учебник

© 2010–2022 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/mapping-primitive-data-types-from-c.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API