Сопоставление примитивных типов данных из C — руководство
Давайте рассмотрим, какие типы данных C доступны в Kotlin/Native и наоборот, а также изучим расширенные сценарии взаимодействия Kotlin/Native с C и сборки Gradle для мультиплатформенных проектов.
В этом руководстве вы:
Для создания библиотеки Kotlin можно использовать командную строку напрямую или с помощью файла скрипта (например, файла .sh или .bat). Однако такой подход плохо подходит для крупных проектов с сотнями файлов и библиотек. Система сборки упрощает процесс: она загружает и кэширует двоичные файлы компилятора Kotlin/Native и библиотеки с транзитивными зависимостями, а также запускает компилятор и тесты. Kotlin/Native поддерживает систему сборки Gradle с помощью плагина Kotlin Multiplatform.
Типы в языке 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, restrict, atomic.
Давайте посмотрим, какие типы данных C доступны в Kotlin.
Создание библиотеки C
В этом руководстве вам не нужно создавать исходный файл lib.c, который необходим только для компиляции и запуска библиотеки C. Для этой настройки потребуется только заголовочный файл .h, необходимый для запуска инструмента cinterop.
Инструмент cinterop создает библиотеку Kotlin/Native (файл .klib) для каждого набора файлов .h. Созданная библиотека обеспечивает взаимодействие вызовов из Kotlin/Native с C. Она содержит объявления Kotlin, соответствующие определениям из файлов .h.
Чтобы создать библиотеку 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++ и перегруженных функций. Подробнее см. в этой теме на Stack Overflow. -
Создайте файл описания
lib.defсо следующим содержимым:headers = lib.h
-
В сгенерированный инструментом cinterop код можно включать макросы и другие определения C. В этом случае тела методов также компилируются и полностью включаются в двоичный файл. Благодаря этой возможности можно создать запускаемый пример без компилятора C.
Для этого добавьте реализации функций C из файла
lib.hв новый файл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.
Создание проекта Kotlin/Native
Чтобы создать файлы проекта:
-
Создайте в папке проекта файл сборки Gradle
build.gradle(.kts)со следующим содержимым:import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget plugins { kotlin("multiplatform") version "2.4.20" } repositories { mavenCentral() } kotlin { macosArm64() // macOS on Apple Silicon // linuxArm64() // Linux on ARM64 platforms // linuxX64() // Linux on x86_64 platforms // mingwX64() // Windows on x86_64 platforms targets.withType<KotlinNativeTarget>().configureEach { val main by compilations.getting val interop by main.cinterops.creating binaries { executable() } } } tasks.wrapper { gradleVersion = "9.7.0" distributionType = Wrapper.DistributionType.BIN }import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget plugins { id 'org.jetbrains.kotlin.multiplatform' version '2.4.20' } repositories { mavenCentral() } kotlin { macosArm64() // Apple Silicon macOS // linuxArm64() // Linux on ARM64 platforms // linuxX64() // Linux on x86_64 platforms // mingwX64() // Windows targets.withType(KotlinNativeTarget).configureEach { compilations.main.cinterops { interop } binaries { executable() } } } wrapper { gradleVersion = '9.7.0' distributionType = 'BIN' }Файл проекта настраивает взаимодействие с C как дополнительный этап сборки. Подробнее о различных способах настройки см. в справочнике по DSL Gradle для Multiplatform.
Переместите файлы
interop.def,lib.hиlib.defв каталогsrc/nativeInterop/cinterop.-
Создайте каталог
src/nativeMain/kotlin. В него нужно поместить все исходные файлы, следуя рекомендациям Gradle использовать соглашения вместо конфигураций.По умолчанию все символы из C импортируются в пакет
interop. -
В
src/nativeMain/kotlinсоздайте файл-заглушкуhello.ktсо следующим содержимым:import interop.* import kotlinx.cinterop.ExperimentalForeignApi @OptIn(ExperimentalForeignApi::class) fun main() { println("Hello Kotlin/Native!") ints(/* fix me*/) uints(/* fix me*/) doubles(/* fix me*/) }
Вы дополните код позже, когда узнаете, как объявления примитивных типов C выглядят со стороны Kotlin.
Изучение API Kotlin, созданных для библиотеки C
Давайте посмотрим, как примитивные типы C сопоставляются с Kotlin/Native, и соответствующим образом обновим пример проекта.
Используйте команду IntelliJ IDEA «Перейти к объявлению» (Cmd + B/Ctrl + B), чтобы перейти к следующему сгенерированному API для функций C:
fun ints(c: kotlin.Byte, d: kotlin.Short, e: kotlin.Int, f: kotlin.Long) fun uints(c: kotlin.UByte, d: kotlin.UShort, e: kotlin.UInt, f: kotlin.ULong) fun doubles(a: kotlin.Float, b: kotlin.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 |
Обновление кода Kotlin
Теперь, когда вы ознакомились с объявлениями C, можно обновить код Kotlin. Итоговый код в файле hello.kt может выглядеть так:
import interop.*
import kotlinx.cinterop.ExperimentalForeignApi
@OptIn(ExperimentalForeignApi::class)
fun main() {
println("Hello Kotlin/Native!")
ints(1, 2, 3, 4)
uints(5u, 6u, 7u, 8u)
doubles(9.0f, 10.0)
}
Чтобы убедиться, что всё работает как ожидалось, запустите задачу Gradle runDebugExecutable<YourTargetName> в IDE или выполните в терминале команду консоли, как в этом примере:
./gradlew runDebugExecutableMacosArm64
Следующий шаг
В следующей части цикла вы узнаете, как типы структур и объединений сопоставляются между Kotlin и C:
См. также
Подробнее о расширенных сценариях читайте в документации «Взаимодействие с C».
© 2010–2026 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