Что такое kotlin native

Kotlin/Native FAQ

How do I run my program?

What is Kotlin/Native memory management model?

Kotlin/Native provides an automated memory management scheme, similar to what Java or Swift provides. The current implementation includes an automated reference counter with a cycle collector to collect cyclical garbage.

How do I create a shared library?

How do I create a static library or an object file?

How do I run Kotlin/Native behind a corporate proxy?

How do I specify a custom Objective-C prefix/name for my Kotlin framework?

How do I rename the iOS framework?

The default name is for an iOS framework is

How do I enable bitcode for my Kotlin framework?

By default gradle plugin adds it on iOS target.

For debug build it embeds placeholder LLVM IR data as a marker.

For release build it embeds bitcode as data.

Setting this in a Gradle DSL:

Why do I see InvalidMutabilityException?

How do I make a singleton object mutable?

Currently, singleton objects are immutable (i.e. frozen after creation), and it’s generally considered good practise to have the global state immutable. If for some reason you need a mutable state inside such an object, use the @konan.ThreadLocal annotation on the object. Also the kotlin.native.concurrent.AtomicReference class could be used to store different pointers to frozen objects in a frozen object and automatically update them.

How can I compile my project with unreleased versions of Kotlin/Native?

First, please consider trying preview versions.

In case you need an even more recent development version, you can build Kotlin/Native from source code: clone Kotlin repository and follow these steps.

Источник

Kotlin Native. Работаем с потоками с корутинами и без. Ч1

Что такое kotlin native. Смотреть фото Что такое kotlin native. Смотреть картинку Что такое kotlin native. Картинка про Что такое kotlin native. Фото Что такое kotlin native

Всем доброго дня! С вами Анна Жаркова, ведущий мобильный разработчик компании Usetech. Совсем недавно компания JetBrains выпустила preview новой модели управления памятью. Это отличный повод сделать подробный ее разбор на практике, а также сравнить с моделью, используемой в KMM в текущих версиях. Но для начала неплохо было бы поговорить о тех возможностях работы в Kotlin Native, которые мы на практике не используем.

Если вы уже знакомы с тем, как работать с корутинами в Kotlin/Native и/или читали предыдущие статьи 1 и 2 автора, то пролистайте немного вниз. Материал может немного повторяться.

Когда мы работаем с Kotlin и Kotlin Multiplatform, то самым и простым удобным способом для настройки работы с многопоточностью в приложении являются Kotlin Coroutines. Наша задача сводится к настройке скоупов CoroutineScope для запуска корутин и suspend функций в основном потоке и фоновом. Т.к. в разных платформенных версиях языка Kotlin этот механизм реализуется по-разному, то необходимо кастомизировать получение контекста корутин с помощью expect/actual:

В случае Kotlin JVM и Android у нас проблем нет (у Kotlin JVM вообще проблем нет, поэтому мы его и не рассматриваем) :

Мы просто используем доступные диспетчеры корутин Main и Default (можно взять IO).

Но в случае iOS и Kotlin Native не все так просто. Мы, конечно, можем использовать те же самые диспетчеры Main и Default, но при переключении контекста запроса мы получим исключение:

Что такое kotlin native. Смотреть фото Что такое kotlin native. Смотреть картинку Что такое kotlin native. Картинка про Что такое kotlin native. Фото Что такое kotlin native

Но если для основного потока использование такого MainDispatcher корректно, для для фонового потока мы не сможем работать с dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT.toLong(), 0.toULong()), потому что эта очередь не привязана ни к одному потоку. Поэтому нам стоит поменять вызов на MainDispatcher для обоих контестов.

Аннотация ThreadLocal используется для корректного шаринга неизменяемого объекта (синглтона) между разными потоками.

Кого-то может смутить корректность получившегося решения. Но так советуют разработчики технологии:

Что такое kotlin native. Смотреть фото Что такое kotlin native. Смотреть картинку Что такое kotlin native. Картинка про Что такое kotlin native. Фото Что такое kotlin native

В качестве примера корректности такого поведения разбирается асинхронная работа с сетевыми запросами через библиотеку Ktor. Действительно большинство случаев, когда нам в мобильном приложении нужно работать с разными потоками, сводятся к сетевым запросам. И при разработке с помощью Kotlin Multiplatform в основном все мы используем готовую библиотеку Ktor, которая уже реализует всю асинхронную работу под капотом.

А что же нам делать, если наша асинхронная работа не связана с сетевыми запросами, и/или мы не хотим использовать Ktor? Да, многопоточные корутины под Kotlin/Native не поддерживаются (вернее, поддерживаются, но не в основных ветках, а, например, реализациях «1.5.0-native-mt»), но нам же надо что-то делать.

Можем, конечно, попробовать осуществлять маршрутизацию в GlobalScope, ведь он позволяет выполнять корутины именно в фоне. Но это не рекомендованное решение, потому что невозможно отследить выполнение такой корутины и управлять ею. Также это создает потенциальные утечки памяти. Поэтому рекомендуется собирать ссылки на job, которые мы запускаем в GlobalScope, и ожидать их окончания.

Что же нам делать в таком случае? Обратимся к опыту предшественников, т.е Ktor, а также документации по многопоточности в Kotlin Native.

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

В данном случае будем делать разные реализации классов сетевых клиентов под iOS и Android не с помощью expect/actual, а путем создания классов с общим интерфейсом, через который мы и будем к нашим клиентам обращаться:

Для iOS будем использовать тот же механизм NSURLSession, что и при нативной разработке, т.к весь Network фреймворк нам доступен в нативном модуле IOS общей части. Единственное, что из-за смены контекстов мы можем работать с сессией только через делегат:

В качестве решения для выполнения кода в фоновом потоке мы рассмотрим Worker. Worker является механизмом Kotlin Native для работы с многопоточностью из-под коробки. Каждый worker представляет собой некую очередь работы, с помощью которой можно выполнять некоторые задачи в отдельных потоках. И на каждый worker создается свой отдельный поток:

Future создается при запуске некоторого функционального блока, который мы передаем в worker.execute для выполнения в producer. Мы также можем отследить выполнение future с помощью сохранения в коллекцию ссылки на него (главное, не забыть потом очистить). Чтобы наш блок выполнялся потокобезопасно, используем параметр TransferMode.SAFE и используем расширение для заморозки нашего блока:

Также мы можем получить из нашего future результат нашей работы с помощью consume и отправить его в некоторый callback-блок:

Мы можем вызвать выполнение нашего callback и в главном потоке. Для этого создаем обертку, где мы DispatchQueue.Main будем вызывать наш замороженный блок:

Еще один момент, прежде, чем мы применим наш worker к коду. Чтобы мы не столкнулись с InvalidMutabilityException: mutation attempt of frozen, нам потребуется заморозить практически все параметры, которые мы используем для нашего сетевого запроса:

И теперь нам надо как-то собирать ответ, который может прийти не весь сразу, а порциями, в массив байтов:

Но тут мы получим краш с исключением заморозки. Просто потому, что при работе с замороженными блоками мы заморозили и сетевой клиент, и все его свойства и переменные. И изменить наш массив данных мы просто так не можем.

На помощь нам приходит API AtomicReference. Это не костыль, а полноценное, рекомендуемое и рабочее решение. AtomicReference держит ссылку на замороженный объект, который можно изменять. Для этого добавим расширение, превращающее наши объекты в атомарные, и изменим код:

Также добавим очистку AtomicReference после окончания работы, чтобы предотвратить захламление памяти и утечки:

В принципе готово. Мы сможем обращаться к нашему клиенту таким образом:

В итоге мы обошлись без скоупов корутин при запросе. И реализовали собственный асинхронный клиент iOS. Но это еще не все, что мы можем сделать в следующей части мы рассмотрим, как работать с DetachedObjectGraph и использовать Kotlin Flow для удобства.

Источник

Расширение PHP и Kotlin Native. Часть третья, наверное финальная

Что такое kotlin native. Смотреть фото Что такое kotlin native. Смотреть картинку Что такое kotlin native. Картинка про Что такое kotlin native. Фото Что такое kotlin nativeВ первой части рассказываются совсем базовые вещи про настройку инструментария и общие концепции.

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

В этой статье будет чуть больше хардкора про интероп Си и K/N, много макросов, боли, безысходности и «лучей добра». Конечно же будет глава с рассказом о достижениях (сам себя не похвалишь… и в качестве бонуса рассказ о эпичном факапе.

Disclaimer: всё нижеследующее рассматривается в контексте написание библиотеки для PHP.

Глава первая. Интероп наивный

Про то, как использовать K/N функций в Си описано в первой части цикла. Соответственно тут я расскажу, как использовать функции Си в K/N.

Официальная документация довольно скупа и лаконична, однако, для простых проектов, ее вполне достаточно.

Если вкратце, то надо создать специальный файл с расширением .def и указать в нем необходимые заголовочные файлы.

Потом скормить его программе под названием cinterop.

На выходе вы получите библиотеку libphp.klib, содержащую llvm bitcode и различную мета-информацию.

Дальше можно смело пользоваться описанными в заголовочном файле функциями и макросами ( #define ), не забыв подключить библиотеку на этапе компиляции.

Но есть нюанс. И не один.

В том виде, как описано выше, библиотека не соберётся

Почему? А потому, что в php.h присутствуют следующие строки:

Тут надо заметить, что компиляцией библиотеки занимается все же llvm, а у него есть ключ -I, а у cinterop есть ключ -copt. Ну вы поняли. В итоге, для компиляции php.h достаточно вот такой команды.

Макросы. Я вас люблю и ненавижу! Хотя нет, просто ненавижу.

Every C macro that expands to a constant is represented as Kotlin property. Other macros are not supported.

А потом вспоминаем, что расширение PHP — это макрос на макросе и макросом погоняет и стараемся не расплакаться.

Но не все так плохо. Для обхода подобной ситуации разработчики K/N предусмотрели моток синей изоленты для примотки к def-файлу custom declarations. Выглядит оно таким образом (для примера возьмем макрос Z_TYPE_P )

Теперь в коде K/N можно будет использовать функцию __zp_get_arg_type

Глава вторая. PHP INI-settings или макрос с подвыподвертом.

Это «луч добра» в сторону исходников PHP.

Для извлечения настроек предусмотрено 4 макроса:

Где val — строка с именем настройки.

Уже заметили его «фатальный недостаток»?

Когда вы используете его через прокси-функцию из .def-файла — карета превращается в тыкву, а sizeof(name) возвращает размер указателя. Шах и мат Kotlin Native.

Вариантов обхода, собственно, всего два.

Глава третья. Дебаг? Какой дебаг?

Акт 1 — интероп.

В один прекрасный момент, после приматывания синей изолентой к def-файлу 20-ти очередных прокси-функций, я получил замечательную ошибку.

Что такое kotlin native. Смотреть фото Что такое kotlin native. Смотреть картинку Что такое kotlin native. Картинка про Что такое kotlin native. Фото Что такое kotlin native

Комментим половину, пересобираем, если повторилось комментим половину оставшегося, собираем… А учитывая, что процесс компиляции хидеров достаточно долог… (да, так показалось быстрее, чем лазить по десятку исходных файлов и скурпулезно, с лупой, выверять).

Второй «луч добра» уходит в сторону JetBrains.

Что такое kotlin native. Смотреть фото Что такое kotlin native. Смотреть картинку Что такое kotlin native. Картинка про Что такое kotlin native. Фото Что такое kotlin native

Акт 2 — рантайм.

Получаю в рантайме segmentation fault. Ну ок, бывает. Лезу в отладчик. Эммм… ШТА?

Что такое kotlin native. Смотреть фото Что такое kotlin native. Смотреть картинку Что такое kotlin native. Картинка про Что такое kotlin native. Фото Что такое kotlin native

Глава четвертая. Я налил чай в твой чай, чтобы ты мог пить чай пока пьешь чай.

Тут необходимо рассказать, как работает та фиговина, которую я делаю.

Вы пишите DSL, описывающий будущее расширение PHP, пишите код на K/N с реализацией функций, классов и методов, потом запускаете make и, чудесным образом, получаете готовую библиотеку, которую можно подключать к PHP.

Сборку можно поделить на 4 этапа:

В Си эта задача решается на раз-два.

Казалось бы все просто — бери да переноси в K/N, но вот myClass …

В конечном итоге, реализация этого функционала привела к добавлению двух новых артефактов: .h и .kt на этапе кодогенерации, усложнению этапа cinterop и эпичному факапу, про который расскажу в самом конце.

Глава пятая. Что в имени тебе моем?

Сказ про то, почему:

Да тут даже объяснять особо не нужно. Вот во что превращается ArgumentType.NULL в заголовочном файле котлиновской библиотеки:

И вот как на такое реагирует `gcc`

Занавес! Следите за именами.

Глава предпоследняя. Сам себя не похвалишь — никто не похвалит.

По большому счету, поставленных перед собой целей я достиг. В тему погрузился, «фреймворк» для написания PHP-расширений на Kotlin Native, в целом, готов. Осталась добавить некоторый, не самый критичный, функционал и отполировать.

Сам проект и, я надеюсь, хорошую документацию к нему, можно посмотреть на гитхабе.

Что могу сказать про K/N? Только хорошее. Писать на нем одно удовольствие, а мелкие косяки и шероховатости вполне можно списать на то, что он еще даже не выбрался из колыбели 🙂

Глава последняя. Лучи добра, без кавычек.

А вот теперь абсолютно серьезно и с глубоким уважением хочу поблагодарить ребят из JetBrains и резидентов slack-канала Kotlin Native. Вы супер!

И отдельное спасибо Николаю Иготти.

Что такое kotlin native. Смотреть фото Что такое kotlin native. Смотреть картинку Что такое kotlin native. Картинка про Что такое kotlin native. Фото Что такое kotlin native

Что такое kotlin native. Смотреть фото Что такое kotlin native. Смотреть картинку Что такое kotlin native. Картинка про Что такое kotlin native. Фото Что такое kotlin native

Бонус. Эпичный факап.

Контекст описан в четвертой главе.

Собственно когда все было дописано до состояния, в котором компилировалось без ошибок, возникла проблема — во время тестирования, PHP открылся мне с совершенно незнакомой ранее стороны.

«Фигасе!» — подумал я, полез в исходники PHP и нашел вот такой кусок.

«Фигасе!» — снова подумал я.

На тот момент, когда я догадался взглянуть на реально использующийся на linux-хосте php.h(7.1.8), а не на тот, который утянул с гитхаба из master-бранча(7.3.х), прошли сутки. Прям стыдно.

Но, как оказалось, дело было не в бобине.

Корректный код проверки на рекурсию, на всех подконтрольных мне этапах жизни объекта, рапортовал, что все ок и должно работать. А это значит, что стоит внимательно присмотреться к тем местам которые я не контролирую. Таковое нашлось ровно одно — в котором мой объект возвращается функции var_dump

Вот тут то мне стало стыдно во второй раз. Я, совершенно на голубом глазу, пихал zval* туда, где ждали zend_object* и потратил на поиск ошибки почти два дня.

Спасибо за внимание, всем Kotlin! 🙂

PS. Если найдется добрая душа, которая вычитает мой корявый английский и поправит документацию — благодарности моей не будет предела.

Источник

How to Start with Kotlin/Native?

Что такое kotlin native. Смотреть фото Что такое kotlin native. Смотреть картинку Что такое kotlin native. Картинка про Что такое kotlin native. Фото Что такое kotlin native

Что такое kotlin native. Смотреть фото Что такое kotlin native. Смотреть картинку Что такое kotlin native. Картинка про Что такое kotlin native. Фото Что такое kotlin native

Kotlin is becoming more and more popular. It took second place in most Loved and fourth place in most wanted technologies in last Stack Overflow Developers Survey!

One of the reasons why Kotlin community is growing is that (starting from version 1.2) includes support for multiplatform projects. A Kotlin multiplatform project allows to compile the same code to multiple target platforms:

Kotlin/Native

We can target 3 OS for Desktop, the 2 most popular OS for mobile, and Raspberry Pi!

Что такое kotlin native. Смотреть фото Что такое kotlin native. Смотреть картинку Что такое kotlin native. Картинка про Что такое kotlin native. Фото Что такое kotlin native Что такое kotlin native. Смотреть фото Что такое kotlin native. Смотреть картинку Что такое kotlin native. Картинка про Что такое kotlin native. Фото Что такое kotlin native

That’s the theory. Let’s check how it looks in practice.

Configuring environment for Kotlin/Native development

Let’s start our adventure with installing CLion. In order to use Kotlin in our projects, we have to install a couple of plugins, namely the Kotlin plugin which provides core support for the language, and the Kotlin/Native plugin which adds functionality for native support. Moreover, the second plugin give us a couple of existing projects templates. I would recommend you to use the CLion Early Access Program builds, because it contains support for most recent Kotlin/Native plugins.

Kotlin/Native gradle plugin

Other projects using Kotlin/Native

Summary

To sum up, we gained some basic knowledge about Kotlin/Native and sample project setup. As you could read there are some pros of using it in our applications, but there are many cons that makes Kotlin/Native really hard to use:

CLion is the only IDE which supports Kotlin/Native, which is problematic for multiplatform projects

CLion doesn’t support Gradle

Lack of API documentation

Lack of support for Kotlin/Native in multiplatform project

Still no stable version

Kotlin Native is still under development, but in my opinion it looks like it can be a great tool in the nearest future.

Despite all the cons I’ve mentioned above I would like to encourage you to give Kotlin/Native a try!

Источник

Kotlin Native. Работаем с новой моделью памяти

Что такое kotlin native. Смотреть фото Что такое kotlin native. Смотреть картинку Что такое kotlin native. Картинка про Что такое kotlin native. Фото Что такое kotlin native

Всем доброго дня! С вами Анна Жаркова, ведущий мобильный разработчик компании Usetech. Продолжаем рассматривать способы многопоточный работы в Kotlin Native.
В предыдущих статьях мы уже рассмотрели существующие способы работы с многопоточностью
с корутинами и без, и что делать с имеющимися болями. Теперь поговорим о новой модели управления памятью, которая появилась совсем недавно.

31 августа компания JetBrains представили превью новой модели управления памятью в Kotlin Native. Основной упор команда разработчиков сделала на безопасность шаринга между потоками, устранение утечек памяти и освобождение нас от использования специальных аннотаций. Также доработка коснулась Coroutines, и теперь можно без опаски переключаться между контекстами корутин без заморозки. Обновления подхватили и Ktor:

Итак, что же нового появится в версии Kotlin 1.6.0-M1-139:
1. Заявлено, что мы можем убрать все freeze() блоки (в том числе и во всех фоновых Worker), и переключаться между контекстами и потоками без каких-либо проблем.

2.Использование AtomicReference или FreezableAtomicReference не приводит к утечкам памяти.

3.При работе с глобальными константами не нужно теперь использовать SharedImmutable.

4.При работе с Worker.execute producer больше не требует возвращать изолированный подграф объектов.

Однако есть и нюансы:
1. Необходимо оставлять заморозку при работе с AtomicReference. В качестве альтернативы мы можем использовать FreezableAtomicReference или AtomicRef из atomicfu . Однако, нас предупреждают, что atomicfu еще не достигла версии 1.х.

2.При вызове suspend функции Kotlin в Swift ее completion handler блок может не прийти в main thread. Т.е добавляем DispatchQueue.main.async<. >, если нам нужно.

3.deInit Swift/ObjC объктов может вызываться в другом потоке.

4.Глобальные свойства инициализируются лениво, т.е при первом обращении. Ранее глобальные свойства инициализировались при запуске. Если вам нужно поддерживать это поведение, то добавляем теперь аннотацию @’EagerInitialization. Рекомендовано ознакомиться с документацией перед использованием.

Нюансы есть и в работе с корутинами, в версии поддерживающей новую модель управления памятью:

1.Мы можем работать в Worker с Channel и Flow без заморозки. И в отличии от native-mt версии заморозка, например, канала заморозить все его содержимое, что может не ожидаться.

2.Dispatchers.Default теперь поддерживается global queue.

3.newSingleThreadContext и newFixedThreadPoolContext теперь можно использовать для создания диспетчера корутин с поддержкой пула одного или нескольких разработчиков.

4.Dispatchers.Main связан с main queue для Darwin и отдельным Worker для других платформ Native. Поэтому рекомендовано не использовать его для работы с Unit тестами, так как ничего не будет вызвано в очереди главного потока.

Нюансов много, есть определенные проблемы с перформансом и известные баги, о которых команда разработки написала предупредительно в документации. Но это пока превью (даже не альфа).

Что ж, давайте попробуем настроить наше решение из предыдущих статей под новую версию модели управления памяти.
Для установки версии 1.6.0-M1-139 добавим некоторые настройки:

И разумеется, добавим зависимость для корутин:

Важно! Если у вас не установлен Xcode версии 12.5 или выше, обязательно скачайте и поставьте. Это минимальная совместимая версия с 1.6.0-M1-139. Если у вас установлено уже несколько версий Xcode, в том числе и более низкие, то поменяйте на подходящую с помощью xcode-select, закройте проект Kotlin Multiplatform и запустите Invalidate cache and Restart. Иначе получите ошибку о несовместимости версии.

Начнем с уборки freeze() блоков из бескорутиновой версии:

Также уберем заморозку с параметров, которые мы используем для UrlSession (у нас нативный сетевой клиент):

Для полного избавления от заморозок меняем AtomicReference на FreezableAtomicReference:

И подправляем код, где мы атомарные ссылки используем:

Код так и дышит чистотой и просто летает, несмотря на то, что GC (в котором могут быть боли) у нас не поменялся.

Теперь подтюнингуем пример с корутинами:

Для начала мы воспользуемся диспетчерами по умолчанию. Чтобы проверить магию GlobalQueue, выведем данные о контексте в блоке под управлением ioDispatcher:

Убираем заморозки при работе с Flow и/или Channel:

Все работает, отлично и быстро. Не забываем вынести ответ в очередь main thread:

Важно! Для предотвращения утечек на стороне iOS, особенно в случае большого количества различных объектов Swift/ObjC, и вспоможения GC оборачиваем блоки вызова и работы с ответом в autoreleasepool.

Теперь попробуем следующее. Запустим на MainScope, но с помощью newSingleThreadContext укажем другой фоновый диспетчер:

Все отрабатывает без запинок. С наших разработческих плеч совсем скоро свалится гора забот.
Но остается жирное «НО». Не все библиотеки, которые мы используем в приложениях KMM, готовы к новой модели памяти, новому подходу к заморозкам и передаче между контекстами. Мы можем получить исключение InvalidMutabilityException или FreezingException.
Поэтому для них в приложениях с версией 1.6.0-M1-139 придется отключить встроенную заморозку:

Источник

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

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