0Pricing
Kotlin Academy · Урок

Взаимодействие с C с помощью cinterop и файлов .def

Вызывайте библиотеки C из Kotlin/Native с помощью инструмента cinterop и файлов определений

«Взаимодействие с C с помощью cinterop и файлов .def» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.

Зачем нужна интеграция с C

Kotlin/Native может напрямую вызывать библиотеки C — без оболочек JNI и промежуточного слоя. Это позволяет использовать системные библиотеки платформы, драйверы оборудования и любые совместимые с C библиотеки из кода Kotlin, скомпилированного в нативные двоичные файлы.

Файл .def

Файл .def описывает импортируемую библиотеку C. В нём указываются заголовочные файлы, имя библиотеки и необязательные флаги компилятора и компоновщика. Поместите его в src/nativeInterop/cinterop/:

# src/nativeInterop/cinterop/libcurl.def
headers = curl/curl.h
headerFilter = curl/**
linkerOpts.linux = -lcurl
linkerOpts.macos = -lcurl

Регистрация интеграции в Gradle

Укажите файл .def в блоке compilations цели:

kotlin {
    linuxX64 {
        compilations["main"].cinterops {
            val libcurl by creating {
                defFile(project.file("src/nativeInterop/cinterop/libcurl.def"))
            }
        }
    }
}

Запуск cinterop

Запустите ./gradlew cinteropLibcurlLinuxX64, чтобы сгенерировать .klib из заголовочных файлов C. Сгенерированные привязки Kotlin появятся в build/cinterop/ и автоматически будут добавлены в путь к классам компиляции.

Использование функций C в Kotlin

После генерации импортируйте пакет, объявленный в файле .def, и вызывайте функции C как функции Kotlin. Типы указателей представлены как CPointer:

import libcurl.*
import kotlinx.cinterop.*

fun fetchUrl(url: String): String = memScoped {
    val handle = curl_easy_init() ?: error("curl init failed")
    curl_easy_setopt(handle, CURLOPT_URL, url.cstr.ptr)
    curl_easy_perform(handle)
    curl_easy_cleanup(handle)
    "done"
}

memScoped: память, выделяемая в стеке

memScoped { } создаёт область памяти, в которой нативные выделения (alloc(), allocArray()) автоматически освобождаются при выходе из блока. Всегда используйте эту конструкцию для временной памяти C, чтобы избежать утечек.

memScoped {
    val value = alloc<IntVar>()
    value.value = 42
    println(value.value)  // 42
    // freed automatically at end of memScoped
}

Закрепление объектов Kotlin для C

Чтобы передать адрес объекта Kotlin функции C (например, функции обратного вызова), закрепите его с помощью StableRef или Pinned, чтобы сборщик мусора не мог его переместить:

val stableRef = StableRef.create(myKotlinObject)
try {
    c_function_expecting_user_data(stableRef.asCPointer())
} finally {
    stableRef.dispose()
}

Строки C и строки Kotlin

Преобразуйте String Kotlin и const char* C с помощью следующих средств:

  • "hello".cstr → CValues, допустимо внутри memScoped
  • cPointer.toKString() → строка Kotlin из CPointer<ByteVar>
memScoped {
    val cStr = "Hello, C!".cstr.ptr   // CPointer<ByteVar>
    val back = cStr.toKString()         // "Hello, C!"
}

Доступ к структурам

Структуры C превращаются в классы Kotlin со свойствами. Получайте доступ к полям структуры с помощью оператора точки. Выделяйте структуры с помощью alloc() внутри memScoped { }:

memScoped {
    val addr = alloc<sockaddr_in>()
    addr.sin_family = AF_INET.convert()
    addr.sin_port = htons(8080u).convert()
}

Встраивание кода C

Для коротких фрагментов C используйте блок cCode в файле .def, чтобы написать встроенный код C, который будет скомпилирован вместе с привязкой:

# In .def file
headers = stdio.h
---
// Inline C code after ---
static inline int add(int a, int b) { return a + b; }

Отладка проблем взаимодействия с C

Распространённые проблемы: отсутствуют заголовочные файлы (проверьте headerFilter), отсутствуют флаги компоновщика (добавьте linkerOpts), типы не совпадают (проверьте API сгенерированного .klib). Включите подробный вывод cinterop с помощью -verbose в файле def или в конфигурации задачи Gradle.

Проверка

Каково назначение memScoped { } во взаимодействии Kotlin/Native с C?

Итоги: взаимодействие с C с помощью cinterop и файлов .def

Главные выводы:

  • Файл .def задаёт заголовочные файлы, параметры компоновщика и необязательный встроенный код C
  • Зарегистрируйте его в Gradle с помощью cinterops { val name by creating { defFile(...) } }
  • Запустите задачу Gradle cinterop<Name><Target>, чтобы сгенерировать привязки
  • Используйте memScoped { } для временных нативных выделений памяти
  • Закрепляйте объекты, существующие длительное время, с помощью StableRef; преобразуйте строки с помощью .cstr / .toKString()

Часто задаваемые вопросы

Урок «Взаимодействие с C с помощью cinterop и файлов .def» бесплатный?

Да — полный текст урока «Взаимодействие с C с помощью cinterop и файлов .def» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.

Чему я научусь в уроке «Взаимодействие с C с помощью cinterop и файлов .def»?

Вызывайте библиотеки C из Kotlin/Native с помощью инструмента cinterop и файлов определений Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Kotlin Academy?

Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Взаимодействие с C с помощью cinterop и файлов .def»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Kotlin Academy?

Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Обзор Kotlin/Native: цели, набор инструментов и компиляция
  2. Управление памятью в Kotlin/Native: новый MM
  3. Взаимодействие с C с помощью cinterop и файлов .def
  4. Kotlin/WASM: компиляция в WebAssembly для браузера
← Назад к Kotlin Academy