Создание приложения с использованием взаимодействия с C и libcurl — руководство
В этом руководстве показано, как с помощью IntelliJ IDEA создать приложение командной строки. Вы узнаете, как создать простой HTTP-клиент, который можно запускать на указанных платформах в нативном режиме с помощью Kotlin/Native и библиотеки libcurl.
В результате получится исполняемое приложение командной строки, которое можно запускать в macOS и Linux и использовать для простых HTTP-запросов GET.
Вы можете использовать командную строку для создания библиотеки Kotlin напрямую или с помощью файла сценария (например, файла .sh или .bat). Однако этот подход плохо подходит для крупных проектов с сотнями файлов и библиотек. Система сборки упрощает процесс: она загружает и кэширует двоичные файлы компилятора Kotlin/Native и библиотеки с транзитивными зависимостями, а также запускает компилятор и тесты. Kotlin/Native поддерживает систему сборки Gradle с помощью плагина Kotlin Multiplatform.
Перед началом
Скачайте и установите последнюю версию IntelliJ IDEA.
-
Клонируйте шаблон проекта: в IntelliJ IDEA выберите Файл | Создать | Проект из системы контроля версий и используйте этот URL:
https://github.com/Kotlin/kmp-native-wizard
-
Изучите структуру проекта:

Шаблон содержит проект с файлами и папками, необходимыми для начала работы. Важно понимать, что приложение, написанное на Kotlin/Native, может предназначаться для разных платформ, если в коде нет платформенно-зависимых требований. Ваш код находится в каталоге
nativeMainс соответствующимnativeTest. Для этого руководства оставьте структуру папок без изменений. -
Откройте файл
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. Чтобы создать файл её определения:
Выберите папку
srcи создайте новый каталог с помощью команды Файл | Создать | Каталог.Назовите новый каталог nativeInterop/cinterop. Это стандартное расположение файлов заголовков, хотя его можно переопределить в файле
build.gradle.kts, если используется другое расположение.Выберите эту новую вложенную папку и создайте файл
libcurl.defс помощью команды Файл | Создать | Файл.-
Добавьте в файл следующий код:
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=) — они применяются ко всем платформам.
Полный список доступных параметров см. в разделе Файл определения.
Добавление взаимодействия в процесс сборки
Чтобы использовать файлы заголовков, убедитесь, что они генерируются в рамках процесса сборки. Для этого добавьте следующий блок 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.
Компиляция и запуск приложения
-
Чтобы скомпилировать приложение, запустите задачу Gradle
runDebugExecutable<YourTargetName>из списка задач или выполните команду в консоли терминала, например:./gradlew runDebugExecutableMacosArm64
В этом случае часть, сгенерированная инструментом cinterop, неявно включается в сборку.
-
Если при компиляции не возникло ошибок, нажмите зелёный значок Запустить на поле рядом с функцией
main()или используйте сочетание клавиш Shift + Cmd + R/Shift + F10.IntelliJ IDEA откроет вкладку Запустить и покажет вывод — содержимое сайта example.com:

Вы видите фактический результат, потому что вызов curl_easy_perform выводит его в стандартный поток вывода. Это можно отключить с помощью curl_easy_setopt.
Что дальше
Узнайте больше о взаимодействии Kotlin с C.
© 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