kotlin_dev_post

Kotlin Native — подключение пользовательской динамической библиотеки на языке C

Как вы можете знать, уже широко известный язык программирования Kotlin предоставляет возможность создания программ для различных платформ: JVM, JS и Native, последний из которых на сегодняшний день подвергается активному развитию. С релизом Kotlin 1.3 проект Kotlin Native вышел в стадию beta.

И как можно догадаться из названия, Kotlin Native позволяет писать и компилировать код на Kotlin под нативные платформы, например iOS или Linux, что предоставляет широкие возможности для создания мультиплатформенных проектов с единой кодовой базой.

Помимо компиляции Kotlin под конкретную платформу, имеется возможность использовать уже готовые нативные библиотеки, например, на языке C, что избавляет разработчиков от необходимости заново переписывать целые проекты.

В данной статье приводится пример простейшего проекта для Kotlin Native, в котором производится вызов функций из уже скомпилированной пользовательской динамической библиотеки, которая была написана на языке С.

Что используется:

  • ОС Ubuntu 16.04
  • IDE IntelliJ IDEA 2018.3.2 (Community Edition)
  • Gradle плагин для сборки проекта kotlin-multiplatform 1.3.40

Очень важно, что статья актуальна для конкретной версии Gradle плагина для сборки проекта. Поскольку на момент написания статьи технология Kotlin Multiplatform всё ещё является экспериментальной, то в будущем вполне возможны изменения как в плагине для сборки, в самой технологии, так и непосредственно в языке Kotlin.

Пользовательская динамическая библиотека

Для данного примера я у себя нашел небольшую простую библиотеку, которая содержит единственную функцию для подсчета энтропии Реньи для массива вещественных чисел double. В каталоге с проектом (в моем случае: /home/tetraquark/dev/c/entropylib ) для данной библиотеки находятся файлы исходников, заголовочные файлы и уже скомпилированная динамическая библиотека libentropy.so. Содержание заголовочного файла очень простое:

Теперь необходимо создать проект Kotlin Native, в котором будет использоваться нативная библиотека.

Проект Kotlin Native

При создании проекта в IDEA выбираем раздел Kotlin и тип проекта Kotlin/Native.

kn_sharedlib_screen_1

Умная IDE сама создаст нужные файлы и каталоги. Но для успешного подключения сторонней нативной библиотеки необходимо самостоятельно подкорректировать скрипт build.gradle для используемой системы сборки Gradle. Ниже приведен полныйкод скрипта build.gradle, который у меня получился:

После редактирования скрипта необходимо выполнить синхронизацию проекта. Внутри блока cinterops последовательно перечисляются все подключаемые нативные библиотеки. В данном случае используется единственная динамическая библиотека, поэтому присутствует единственный блок с названием entropylib. Внутри данного блока указываются различные параметры, например, опции для компилятора с указанием каталога для заголовочных файлов. Всё указывается как для gcc.

Далее для успешной генерации всех нужных файлов для cinterop необходимо выполнить следующее:

1) В каталоге src необходимо создать каталог nativeInterop;

2) В только что созданном каталоге nativeInterop, необходимо создать еще один каталог cinterop;

3) В каталоге nativeInterop/cinterop создаем текстовый файл entropylib.def (имена .def файлов должна совпадать с названиями блоков, которые описаны внутри cinterops в build.gradle);

4) В данном файле описывается параметры для подключаемой конкретной библиотеки, указываются необходимые заголовочные файлы, по которым будут создаваться Kotlin обертки, которые уже используются в Kotlin проекте. В данном случае содержание файла очень простое (указывается единственный заголовочный файл библиотеки):

В итоге, в нашем случае структура проекта выглядит следующим образом:

kn_sharedlib_screen_2

Теперь можно вызывать cinterop. Для этого воспользуемся IDEA, открыв окно задач Gradle. И в разделе задач Tasks выполняем задачу interop/cinteropEntropylibLinux (в случае других названий блоков в cinterops в build.gradle, название задачи interop будет слегка отличаться).

kn_sharedlib_screen_3

Либо запускаем задачу через gradlew в терминале:

В результате успешной работы cinterop, будет создана библиотека .klib и Kotlin обертки над подключаемой нативной библиотекой. Можно открыть и посмотреть, как выглядит эта обертка, которую можно найти примерно тут:

kn_sharedlib_screen_4

Теперь можно начать писать код для Kotlin проекта с использованием динамической библиотеки. IDE при создании проекта любезно автоматически создала файл src/linuxMain/SampleLinux.kt, в котором находится функция main. Там я и написал следующие строки кода:

Сборка и запуск проекта

Осталось собрать получившийся проект и запустить программу. Я проводил сборку с помощью Gradle. Сборку можно выполнить, запустив Gradle задачу build:
kn_sharedlib_screen_5

Либо запускаем задачу через gradlew в терминале:

В случае операционной системы Linux после успешной компиляции в терминале необходимо добавить к переменной среды LD_LIBRARY_PATH полный путь до файла динамической библиотеки, в моем случае это выглядит следующим образом:

Всё готово, можно проверять. Результаты компиляции (исполняемые файлы с расширением .kexe) находятся в проекте Kotlin Native в каталоге build/bin. В моем случае в каталоге build/bin/linux. Я запускал через терминал так:

Результаты работы:

kn_sharedlib_screen_6

Полезные ссылки:

One thought on “Kotlin Native — подключение пользовательской динамической библиотеки на языке C

  1. Интересно, нужно попробовать. Если все настолько просто, то это очень круто. В Python создание обертки для динамической библиотеки — это прямо боль (или я еще не научился это правильно делать))

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">