Spec-Zone.ru › Kotlin 2

Создание приложения с использованием взаимодействия с C и libcurl — руководство

Импорт библиотек C находится в статусе бета-версии. Все объявления Kotlin, сгенерированные инструментом cinterop из библиотек C, должны иметь аннотацию @ExperimentalForeignApi.

Для некоторых API платформенных библиотек Native, поставляемых вместе с Kotlin/Native (например, Foundation, UIKit и POSIX), требуется явно разрешить их использование.

В этом руководстве показано, как с помощью IntelliJ IDEA создать приложение командной строки. Вы узнаете, как создать простой HTTP-клиент, который можно запускать на указанных платформах в нативном режиме с помощью Kotlin/Native и библиотеки libcurl.

В результате получится исполняемое приложение командной строки, которое можно запускать в macOS и Linux и использовать для простых HTTP-запросов GET.

Вы можете использовать командную строку для создания библиотеки Kotlin напрямую или с помощью файла сценария (например, файла .sh или .bat). Однако этот подход плохо подходит для крупных проектов с сотнями файлов и библиотек. Система сборки упрощает процесс: она загружает и кэширует двоичные файлы компилятора Kotlin/Native и библиотеки с транзитивными зависимостями, а также запускает компилятор и тесты. Kotlin/Native поддерживает систему сборки Gradle с помощью плагина Kotlin Multiplatform.

Перед началом

  1. Скачайте и установите последнюю версию IntelliJ IDEA.

  2. Клонируйте шаблон проекта: в IntelliJ IDEA выберите Файл | Создать | Проект из системы контроля версий и используйте этот URL:

    https://github.com/Kotlin/kmp-native-wizard
    
  3. Изучите структуру проекта:

    Native application project structure

    Шаблон содержит проект с файлами и папками, необходимыми для начала работы. Важно понимать, что приложение, написанное на Kotlin/Native, может предназначаться для разных платформ, если в коде нет платформенно-зависимых требований. Ваш код находится в каталоге nativeMain с соответствующим nativeTest. Для этого руководства оставьте структуру папок без изменений.

  4. Откройте файл build.gradle.kts — сценарий сборки, содержащий настройки проекта. Обратите особое внимание на следующее в файле сборки:

    import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
    
    kotlin {
        macosArm64()
        linuxArm64()
        linuxX64()
        mingwX64()
    
        targets.withType<KotlinNativeTarget>().configureEach {
            binaries {
                executable {
                    entryPoint = "main"
                }
            }
        }
    }
    
    • Целевые платформы задаются с помощью macosArm64, linuxArm64, linuxX64 и mingwX64 для macOS, Linux и Windows. Полный список см. в разделе поддерживаемые платформы.

    • Блок binaries {} задаёт способ генерации двоичного файла и точку входа приложения. Можно оставить значения по умолчанию.

    • Взаимодействие с C настраивается как дополнительный шаг сборки. По умолчанию все символы из C импортируются в пакет interop. При необходимости можно импортировать весь пакет в файлах .kt. Подробнее о том, как настроить эту возможность.

Создание файла определения

При разработке нативных приложений часто требуется доступ к определённым функциям, не входящим в стандартную библиотеку Kotlin, например к выполнению HTTP-запросов, чтению и записи файлов на диске и т. д.

Kotlin/Native упрощает использование стандартных библиотек C, открывая доступ к обширной экосистеме функций практически для любых задач. В состав Kotlin/Native уже входит набор предварительно собранных платформенных библиотек, предоставляющих стандартной библиотеке некоторые дополнительные распространённые возможности.

В идеальном случае взаимодействие позволяет вызывать функции C так же, как функции Kotlin, с теми же сигнатурами и соглашениями. Здесь пригодится инструмент cinterop. Он принимает библиотеку C и генерирует соответствующие привязки Kotlin, чтобы библиотеку можно было использовать как код Kotlin.

Для генерации этих привязок каждой библиотеке нужен файл определения, обычно с тем же именем, что и у библиотеки. Это файл свойств, в котором точно описано, как следует использовать библиотеку.

В этом приложении для выполнения HTTP-запросов понадобится библиотека libcurl. Чтобы создать файл её определения:

  1. Выберите папку src и создайте новый каталог с помощью команды Файл | Создать | Каталог.

  2. Назовите новый каталог nativeInterop/cinterop. Это стандартное расположение файлов заголовков, хотя его можно переопределить в файле build.gradle.kts, если используется другое расположение.

  3. Выберите эту новую вложенную папку и создайте файл libcurl.def с помощью команды Файл | Создать | Файл.

  4. Добавьте в файл следующий код:

    headers = curl/curl.h
    headerFilter = curl/*
    
    compilerOpts.linux = -I/usr/include -I/usr/include/x86_64-linux-gnu
    linkerOpts.osx = -L/opt/local/lib -L/usr/local/opt/curl/lib -lcurl
    linkerOpts.linux = -L/usr/lib/x86_64-linux-gnu -lcurl
    
    • headers — это список файлов заголовков, для которых нужно сгенерировать заглушки Kotlin. Здесь можно указать несколько файлов, разделив их пробелами. В данном случае это только curl.h. Указанные файлы должны быть доступны по заданному пути (в данном случае это /usr/include/curl).

    • headerFilter указывает, что именно включается. В C также включаются все файлы заголовков, на которые ссылается другой файл с помощью директивы #include. Иногда это не требуется — можно добавить этот параметр, используя шаблоны glob, чтобы настроить включение.

      Можно использовать headerFilter, если вы не хотите включать внешние зависимости (например, системный заголовок stdint.h) в библиотеку взаимодействия. Это также может пригодиться для оптимизации размера библиотеки и устранения возможных конфликтов между системным окружением и предоставляемой средой компиляции Kotlin/Native.

    • Если для определённой платформы требуется изменить поведение, можно использовать формат compilerOpts.osx или compilerOpts.linux, чтобы задать значения параметров для конкретной платформы. В данном случае это macOS (суффикс .osx) и Linux (суффикс .linux). Также можно указывать параметры без суффикса (например, linkerOpts=) — они применяются ко всем платформам.

    Полный список доступных параметров см. в разделе Файл определения.

Для работы примера в системе должны быть установлены двоичные файлы библиотеки curl. В macOS и Linux они обычно включены в состав системы. В Windows её можно собрать из исходного кода (для этого понадобятся Microsoft Visual Studio или инструменты командной строки Windows SDK). Подробнее см. в соответствующей статье в блоге. Кроме того, можно воспользоваться двоичным файлом curl для MinGW/MSYS2.

Добавление взаимодействия в процесс сборки

Чтобы использовать файлы заголовков, убедитесь, что они генерируются в рамках процесса сборки. Для этого добавьте следующий блок compilations {} в файл build.gradle.kts:

targets.withType<KotlinNativeTarget>().configureEach {
    compilations.getByName("main") {
        cinterops {
            val libcurl by creating
        }
    }
    binaries {
        executable {
            entryPoint = "main"
        }
    }
}

Сначала добавляется cinterops, а затем запись для файла определения. По умолчанию используется имя файла. Его можно переопределить с помощью дополнительных параметров:

cinterops {
    val libcurl by creating {
        definitionFile.set(project.file("src/nativeInterop/cinterop/libcurl.def"))
        packageName("com.jetbrains.handson.http")
        compilerOpts("-I/path")
        includeDirs.allHeaders("path")
    }
}

Написание кода приложения

Теперь, когда у вас есть библиотека и соответствующие заглушки Kotlin, вы можете использовать их в приложении. В этом руководстве пример simple.c будет преобразован в Kotlin.

В папке src/nativeMain/kotlin/ замените содержимое файла Main.kt следующим кодом:

import kotlinx.cinterop.*
import libcurl.*

@OptIn(ExperimentalForeignApi::class)
fun main(args: Array<String>) {
    val curl = curl_easy_init()
    if (curl != null) {
        curl_easy_setopt(curl, CURLOPT_URL, "https://example.com")
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L)
        val res = curl_easy_perform(curl)
        if (res != CURLE_OK) {
            println("curl_easy_perform() failed ${curl_easy_strerror(res)?.toKString()}")
        }
        curl_easy_cleanup(curl)
    }
}

Как видите, в версии на Kotlin явные объявления переменных не нужны, но в остальном она практически не отличается от версии на C. Все ожидаемые вызовы библиотеки libcurl доступны и в эквиваленте на Kotlin.

Это буквальный построчный перевод. Этот код также можно написать в более идиоматичном стиле Kotlin.

Компиляция и запуск приложения

  1. Чтобы скомпилировать приложение, запустите задачу Gradle runDebugExecutable<YourTargetName> из списка задач или выполните команду в консоли терминала, например:

    ./gradlew runDebugExecutableMacosArm64
    

    В этом случае часть, сгенерированная инструментом cinterop, неявно включается в сборку.

  2. Если при компиляции не возникло ошибок, нажмите зелёный значок Запустить на поле рядом с функцией main() или используйте сочетание клавиш Shift + Cmd + R/Shift + F10.

    IntelliJ IDEA откроет вкладку Запустить и покажет вывод — содержимое сайта example.com:

    Application output with HTML-code

Вы видите фактический результат, потому что вызов curl_easy_perform выводит его в стандартный поток вывода. Это можно отключить с помощью curl_easy_setopt.

Полный код проекта можно найти в нашем репозитории на GitHub.

Что дальше

Узнайте больше о взаимодействии Kotlin с C.

31 марта 2026 г.
Kotlin/Native в виде динамической библиотеки — руководствоФайл определения

© 2010–2026 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/native-app-with-c-and-libcurl.html

Spec-Zone.ru

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