Spec-Zone.ru › Kotlin 1.8

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

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

  • Увидите, какие типы данных используются в языке C.

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

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

  • Узнаете, как примитивные типы в Kotlin сопоставляются с C.

Типы данных в языке C

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

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

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

  • указатели

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

Также существуют более специфические типы:

  • логический тип (из 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. Для запуска инструмента cinterop достаточно иметь файл .h. И вам не нужно создавать файл 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, и многоплатформенные сборки с Gradle.

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

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

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

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 = "7.3"
  distributionType = Wrapper.DistributionType.BIN
}
plugins {
    id 'org.jetbrains.kotlin.multiplatform' version '1.8.0'
}

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 = '7.3'
  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 (Перейти | Объявление) или ошибок компилятора, вы видите следующую сгенерированную 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

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

Вы видели все определения, и сейчас пришло время исправить код. Запустите задачу runDebugExecutableNative Gradle в 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 охватывает более сложные сценарии взаимодействия.

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

© 2010–2023 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