Пишем на rust под андроид

Обновлено: 10.08.2022

Последние несколько лет Google поощряет разработчиков писать приложения для Android с помощью Kotlin. Базовая ОС по-прежнему использует C и C++, хотя сегодня Google объявила о поддержке Android Open Source Project (AOSP) для Rust. Из отчета: Это часть работы Google по устранению ошибок безопасности памяти в операционной системе: «Мы вкладываем много усилий и ресурсов в обнаружение, исправление и снижение уровня ошибок этого класса, и эти усилия эффективны для предотвращения большое количество ошибок из-за того, что они попали в выпуски Android. Тем не менее, несмотря на эти усилия, ошибки безопасности памяти по-прежнему являются основной причиной проблем со стабильностью и постоянно составляют около 70% серьезных уязвимостей безопасности Android."

Компания считает, что безопасные для памяти языки, такие как Rust, являются «наиболее экономически эффективным средством предотвращения ошибок памяти» в загрузчике, быстрой загрузке, ядре и других низкоуровневых частях ОС. В отличие от C и C++, где разработчики управляют временем жизни памяти, Rust «обеспечивает гарантии безопасности памяти, используя комбинацию проверок во время компиляции для обеспечения времени жизни/владения объектами и проверок во время выполнения, чтобы гарантировать, что доступ к памяти действителен». Google работал над добавлением этой поддержки в AOSP в течение последних 18 месяцев. Производительность эквивалентна существующим языкам, при этом повышается эффективность текущей песочницы и снижается общая потребность в ней. Это позволяет использовать «новые функции, которые являются более безопасными и менее затратными по ресурсам». Другие улучшения включают параллелизм данных, более выразительную систему типов и более безопасную обработку целых чисел.

Вы можете прочитать:

«Программирование — это сложно» считается вредным

Разработчик с открытым исходным кодом намеренно искажает свои собственные широко используемые библиотеки

Дело против SQL

Не слишком ли сложна современная разработка программного обеспечения?

Линус Торвальдс говорит, что Rust ближе к разработке ядра Linux, и называет C++ «дерьмовым языком»

Google Now поддерживает Rust для разработки ОС Android Подробнее Вход

Google Now поддерживает Rust для базовой разработки ОС Android

Мелкий шрифт: следующие комментарии принадлежат тому, кто их разместил. Мы никоим образом не несем за них ответственности.

Rust — модный язык, продвигаемый не из-за какого-либо технического превосходства, а из-за мемов «переписать его на ржавчине». Slackware и Gentoo жалуются на сложность сборки своих дистрибутивов из-за прокравшихся зависимостей ржавчины, ставящих под угрозу ранее стабильные системы сборки. Теперь Rust захватил Android.

RustemD испортил мне удовольствие от Linux.

Я мало что знаю о RUST, но знаю, что все эти новые языки пытаются решить какую-то проблему.

Реализация может быть хуже, чем преимущества решенной проблемы (много примеров см. в большинстве «новых» функциональных языков), но это отдельный вопрос.

Что касается зависимостей. всегда есть компромиссы при выборе. Если вам не нравится результат, это потому, что вы совершили неправильную сделку, да?

Самая проблематичная сделка заключалась в том, чтобы (пере)переписать rustc на Rust, что привело к проблеме начальной загрузки. Я почти думаю, что кто-то слышал, что «только perl может анализировать Perl» — perl в нижнем регистре — это стандартная версия интерпретатора, Perl в верхнем регистре — это язык — и решил, что это было бы хорошо для языка системного программирования. .

Для сравнения, официальный компилятор Go написан на Go, но gccgo активно отслеживает спецификацию Go, что значительно упрощает проблему начальной загрузки

Да, тот факт, что есть другие приличные (даже хорошие) компиляторы C и C++, является очень большой практической разницей. В этой ситуации вы можете использовать альтернативные компиляторы, чтобы победить взлом Томпсона (с произвольно высокой степенью достоверности). Тот факт, что кто-то *мог* написать конкурирующий компилятор для Rust, не меняет сути сделки, потому что теоретическая возможность не упрощает реальную загрузку — упрощается только фактическое существование другого компилятора.

У Rust определенно есть техническое превосходство. Это становится совершенно очевидным, как только вы начинаете его использовать. В любом случае, сообщество rust не выступает за переписывание вещей в rust просто ради этого, хотя среды, в которых вам приходится запускать ненадежный код, а производительность и безопасность имеют первостепенное значение, такие как веб-браузеры, — это места, где это было бы хорошо. идея.

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

Хотя в какой-то момент я хотел бы углубиться в работу Android-разработчика. Как вы думаете, кто-то, изучающий Android, может лучше изучить Rust для Android-разработки или просто придерживаться Kotlin?

С интуитивной точки зрения кажется, что Kotlin был бы лучше, поскольку системные и UI-библиотеки больше ориентированы на мышление Java/Kotlin и, вероятно, какое-то время не будут так же хорошо сочетаться с конструкциями Rust. Кроме того, Kotlin кажется ближе к Swift, чем Rust (в этом я не уверен).

Итак, я подумал, что было бы интересно узнать, что думают профессиональные разработчики Android.

На сегодняшний день я сделал небольшое количество разработок для Android, ничего такого, что можно было бы считать настоящим приложением.

Обратите внимание, TFA говорит о Rust в AndroidOS, а не об использовании Rust в приложениях.

Rust плохо поддерживается для разработки приложений для Android. Если вы попытаетесь использовать его, вы окажетесь на переднем крае. Поскольку вы утверждаете, что у вас мало опыта работы с приложениями, это, вероятно, будет ошибкой. Вам следует придерживаться Kotlin, пока экосистема Rust для Android не созреет.

Обратите внимание, TFA говорит о Rust в AndroidOS

Спасибо, это единственный раз, когда мне действительно нужно было прочитать TFA. Я предположил, что это означает, что его также можно будет использовать для разработки Android. Ну что ж, тогда, может быть, следующая мобильная платформа.

Используйте Lisp, как это делают все крутые пользователи emacs. Все равно это все притворство, верно?

Считается ли какая-либо ваша разработка iOS «настоящим приложением», я имею в виду настоящего программиста?

Что означает "интуитивная точка зрения"?

Я не думаю, что приложения для Android приближают вас к первому ряду на митингах поддержки Apple. Стив Джобс бы этого не одобрил.

Безопасность важнее всего. Rust значительно сокращает окно атаки для программного обеспечения.
Анализ ржавчины происходит во время компиляции. Это само по себе уменьшает окно атаки.
Нулевая сборка мусора отлично подходит для встроенных и изолированных сред.
Rust to WASM создает очень безопасный код, который может работать в браузере.

Библиотеки? Мне пришлось разветвить два проекта, чтобы мои проекты заработали.

Я думаю, писать на ржавчине — хорошая идея,

Я уверен, что Rust безопаснее, чем C. Но через несколько лет будет интересно посмотреть, действительно ли Rust безопаснее правильно написанного C++ (т. е. с использованием unique_ptr, shared_ptr и т. д., когда это возможно). Если код делает что-то, что все еще требует необработанных указателей в C++, вероятно, потребуется небезопасный раздел в Rust. Та же разница.

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

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

У Rust просто нет многих проблем, потому что язык заботится об этом. Люди просто не могут совершать определенные ошибки. И хотя мы всегда можем сказать, что «конечно, вы не делаете X», и что C, C++ или любой другой ваш любимый язык действительно безопасны, если «правильно написаны», не забывайте, что большинство компаний, которые пишут программное обеспечение на коммерческой основе, наймите самых дешевых кодировщиков, максимально сдвиньте сроки и срежьте углы там, где клиент не увидит.

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

Эти компании будут нанимать Javascripters. Отсюда и неожиданный рост Node.JS на сервере. Они не будут нанимать для C++, но они также не будут нанимать для Rust. Ни один из них не подходит для кода большого объема/низкого качества, которым является Javascript.

«Правильно написанный» C++ требует гораздо меньше усилий, чем плохо написанный C++. «Правильно написанный» C++ может быть таким же простым, как Python, особенно с современными функциями, которые устраняют большую часть шаблонного кода. С тем же успехом я могу написать простой скрипт на C++ для text pro

Эти компании будут нанимать Javascripters. Отсюда и неожиданный рост Node.JS на сервере. Они не будут нанимать для C++, но они также не будут нанимать для Rust. Ни один из них не подходит для кода большого объема/низкого качества, которым является Javascript.

Я согласен с этим, но это временная оценка. Я достаточно уверен, что JS и Node.js исчезнут в течение десяти лет или около того, в том смысле, что импульс находится в другом месте, и пара компаний хорошо зарабатывает, поддерживая устаревшие приложения.

«Правильно написанный» C++ требует гораздо меньше усилий, чем плохо написанный C++. «Правильно написанный» C++ может быть таким же простым, как Python, особенно с современными функциями, которые устраняют большую часть шаблонного кода.Я могу так же легко написать простой скрипт на C++ для обработки текста или настроить и запустить небольшой веб-сервер, как это можно сделать с помощью NodeJS.

Возможно. Я не много писал на C++ в своей жизни, и только в прошлом году выучил Python. Без сомнения, оба они превосходят JS по всем показателям, кроме «используется в браузере» и «имеют в наличии обширный пул дешевых кодеров». Но сравнение было не с JS, а с Rust. И

JS и Node.js исчезнут примерно через десять лет

На самом деле, я надеюсь, что Rust и его мощные возможности webasm станут одной из лопат, которые копают могилу для веб-приложений JS.

Найти небезопасные разделы в rust гораздо проще, чем в C++.

Существуют ли инструменты анализа кода, проверяющие рекомендации, которые могут дать те же гарантии, что и безопасный rust, при условии, что инструмент говорит, что рекомендации были соблюдены? У MISRA, похоже, нет AFAICS.

Но через несколько лет будет интересно посмотреть, действительно ли Rust безопаснее правильно написанного C++

Позвольте мне начать с апелляции к собственному авторитету: я возглавляю команду Android, которая написала наибольшее количество кода Rust для Android, хотя лично я написала очень мало, и приписываю успех проекта полностью своей коллеги.

Под "правильно написанным C++" вы подразумеваете "современный C++", и я думаю, что ответ отрицательный. Rust не безопаснее, чем Modern C++ — при условии, что код C++ никогда не отклоняется от набора идиом, определенных Modern C++, и при условии, что в коде C++ включены исключения (Android отключает их), а весь код и библиотеки защищены от исключений. . И, вероятно, несколько других предостережений, которые придут ко мне позже.

Я думаю, вы поняли.

Rust — это, по сути, та же парадигма программирования, что и современный C++, но с заменой исключений на упрощенную стратегию возврата ошибок, которая обеспечивает принудительную проверку ошибок и делает ее довольно безболезненной. Rust немного более функционален (в смысле слова «функциональный язык», а не в смысле «он работает»), главным образом потому, что его стандартные библиотеки используют более функциональный подход, который увеличивает кривую обучения, но не является фундаментальным. отличительной чертой, поскольку C++ теперь имеет все инструменты, необходимые для того, чтобы быть столь же функциональным, как Rust.

Действительно большая разница в том, что Rust не позволяет вам делать небезопасные вещи за пределами «небезопасного» блока, тогда как C++ позволяет вам незаметно вставлять небезопасный код в любое место и не заставляет вас делать это очевидным. Это означает, что небезопасные блоки в Rust подвергаются тщательному анализу. Кроме того, примерно все команды, пишущие Rust, применяют некоторые нормы в отношении небезопасных блоков, что требует дополнительной документации и более тщательного изучения. Теоретически то же самое можно было бы сделать и в C++ — изолировать и тщательно изучить небезопасный код, — но в Rust язык и компилятор помогают в этом, чего не делают инструменты C++.

Мои выводы таковы: (а) вы правы, будет интересно посмотреть, действительно ли Rust работает лучше, чем правильно написанный C++, и (б) даже если это не так, количество правильно написанных C++ в мире меньше, чем нам всем хотелось бы верить, даже в магазинах с высококвалифицированными инженерами и хорошо развитыми процессами качества, включая обязательные проверки кода и т. д. Поэтому я ожидаю, что Rust будет лучше, чем C++, потому что C++ довольно скорее всего не правильно написано.

Возможно, вы слышали о rust. Это язык системного программирования, разработанный для обеспечения безопасности и скорости работы с памятью. Создан Mozilla для поддержки высокопроизводительного межплатформенного программного обеспечения следующего поколения. Если вы еще этого не сделали, я предлагаю взглянуть на отличный учебный материал, но имейте в виду, что может потребоваться некоторое время, чтобы понять и оценить его, поэтому я предлагаю написать больше, чем просто привет, мир.

Если вы разработчик Android, возможно, вы задаетесь вопросом, как и почему использовать rust на Android. В этой статье в основном рассматривается как. Что касается причины, то наиболее убедительной причиной для нас в Visly является то, что он позволяет нам эффективно и безопасно обмениваться кодом между Android и iOS на языке, с которым гораздо проще работать, чем с C++.

Прежде чем мы начнем, нам нужно убедиться, что у нас настроен набор инструментов rust. Мы предполагаем, что у вас уже есть рабочий набор инструментов для Android, в противном случае вам следует загрузить Android Studio и настроить его в соответствии с любым другим руководством по Android. Нужно убедиться, что вы настроили переменную окружения $ANDROID_HOME. При обычной установке на macOS это значение должно быть ~/Library/Android/sdk .

Далее мы должны убедиться, что в нашей системе установлен rust. Rustup делает это простым однострочником.

Вы можете убедиться, что rust успешно установлен и находится в вашем PATH, запустив rustc --version . После того, как Rust установлен в вашей системе, нам нужно сообщить Rust о том, как выполнять сборку для поддерживаемых архитектур Android. Rust может создавать двоичные файлы для всех видов архитектур, но не по умолчанию. Чтобы добавить соответствующие архитектуры, выполните следующую команду.

Затем нам нужно настроить несколько автономных наборов инструментов для создания rust для различных поддерживаемых архитектур Android. Их нужно установить только один раз для вашей системы, а не несколько раз для каждого проекта, поэтому вместо того, чтобы устанавливать их в папку проекта, мы установим их в наш домашний каталог.

Наконец мы должны рассказать Rust об этих наборах инструментов. Добавьте следующее к ~/.cargo/config , создав файл, если он еще не существует.

Давайте создадим небольшое приложение hello world на rust! Мы начнем с создания нашей библиотеки ржавчины, а затем перейдем к созданию нашего проекта Android Studio.

Это создаст базовую библиотеку ржавчины, управляемую cargo , эквивалентную gradle в ржавчине, которую мы позже будем использовать в нашем проекте Android Studio. Флаг --lib указывает грузу, что мы хотим создать библиотеку, а не исполняемый двоичный файл. Во вновь созданной папке проекта вы найдете Cargo.toml, который очень похож на файл build.gradle и определяет метаданные для вашей библиотеки, а также любые зависимости. Вы также найдете папку src, которая содержит наш исходный код rust. Папка src содержит только файл lib.rs, который сам содержит только пробную тестовую функцию. Мы можем начать с удаления всего в этом файле и замены его следующим.

Затем мы определяем базовую функцию, которая создает новую строку на основе входной строки. Там много чего происходит, так как нам нужно преобразовать строку из строки jni в строку C, в строку ржавчины и обратно. Библиотеки rust jni и ffi делают это довольно безопасным, и позже мы обратимся к некоторым шаблонам, которые мы используем в Visly, чтобы упростить эту задачу. В больших приложениях это не проблема, так как связующий код между Kotlin и Rust может быть довольно небольшим.

Нам также необходимо обновить наш Cargo.toml, чтобы добавить зависимость от библиотеки jni, а также определить имя окончательного двоичного файла и способ его компиляции.

Теперь последнее, что нужно сделать, прежде чем мы будем готовы перейти к нашему проекту Android Studio, — это создать нашу библиотеку для наших поддерживаемых целей.

Студия Android

Пришло время начать новый проект Android Studio и протестировать его в симуляторе. Начните со стандартной настройки проекта, мы будем использовать Kotlin, но вы также можете использовать Java, если хотите. Мы назовем проект android, сохранив его рядом с нашей библиотекой rust в корне rust-android-example.


Откройте MainActivity.kt и вставьте следующий код. Мы объявляем внешнюю функцию hello, которая сообщает Android искать встроенную библиотечную функцию с именем Java_example_com_android_MainActivity_hello. Прежде чем мы сможем вызвать эту функцию, мы должны загрузить нашу библиотеку с помощью System.loadLibrary.

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

Теперь мы можем пересобрать и повторно запустить наше приложение, и мы должны увидеть надпись «Hello World» в Logcat. Поздравляю! Вам удалось скомпилировать и запустить код Rust на Android.

Автоматизировать этот процесс копирования двоичных файлов на самом деле довольно просто с помощью простого скрипта bash.

Теперь сохраните это как rust-android-example/install.sh и просто запустите скрипт после любых обновлений вашего кода rust, чтобы скомпилировать и установить его в свой проект Android Studio. Если вы хотите пофантазировать, вы можете добавить это как шаг сборки в свой файл gradle, чтобы он автоматически запускался каждый раз, когда вы создаете проект Android Studio.

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

Окончательный код для этого руководства и отличная отправная точка, если вы планируете использовать rust на Android, можно найти на GitHub. Если у вас есть какие-либо вопросы или комментарии, напишите мне в Твиттере.

Во вторник компания Google объявила, что в ее версию операционной системы Android с открытым исходным кодом будет добавлена ​​поддержка языка программирования Rust, чтобы предотвратить ошибки, связанные с безопасностью памяти.

С этой целью компания в течение последних 18 месяцев создавала части проекта Android с открытым исходным кодом (AOSP) с помощью Rust, и в настоящее время планируется масштабировать эту инициативу, чтобы охватить больше аспектов операционной системы.

"Управляемые языки, такие как Java и Kotlin, — лучший вариант для разработки приложений для Android", – заявили в Google. "ОС Android широко использует Java, эффективно защищая большие части платформы Android от ошибок памяти. К сожалению, для нижних уровней ОС Java и Kotlin не подходят."

Утверждая, что код, написанный на языках C и C++, требует надежной изоляции при анализе ненадежных входных данных, Google заявил, что метод содержания такого кода в строго ограниченной и непривилегированной изолированной программной среде может быть дорогостоящим, вызывая проблемы с задержкой и дополнительное использование памяти.


Поскольку ошибки безопасности памяти в C и C++ составляют около 70 % серьезных уязвимостей безопасности Android, идея состоит в том, чтобы переключиться на безопасный для памяти язык, такой как Rust, и в первую очередь предотвратить их появление.

"Rust обеспечивает гарантии безопасности памяти, используя комбинацию проверок во время компиляции для принудительного соблюдения срока жизни/владения объектами и проверок во время выполнения, чтобы гарантировать, что доступ к памяти действителен", – отметили в Google.

Несмотря на очевидные преимущества, Google не собирается переписывать весь свой существующий код C и C++ в базовой ОС, вместо этого сосредоточив свои усилия на безопасном для памяти языке на новом или недавно измененном коде, который имеет более высокую вероятность ошибок памяти. .

Некоторые из текущих усилий Google в отношении Rust включают полное переписывание стека Bluetooth для Android, получившего название Gabeldorsche, которое компания начала тестировать, начиная с Android 11 в прошлом году. Также в разработке находится сетевой стек на основе Rust для операционной системы Fuchsia с открытым исходным кодом.

Нашли эту статью интересной? Подпишитесь на THN в Facebook, Twitter и LinkedIn, чтобы читать больше эксклюзивного контента, который мы публикуем.

Загрузите один раз и поделитесь им с Android, iOS и Flutter

Что, если бы я сказал вам, что вы можете использовать один и тот же очень производительный код в Android, iOS или даже во Flutter. В этой статье мы увидим, как добиться этого с помощью Rust.

Но зачем нам что-то подобное?

Представьте, что у вас есть мобильное приложение, которому необходимо обработать звук, чтобы получить некоторое представление о пользователе, но вы не хотите, чтобы звук отправлялся на сервер для обработки. Вы хотите сохранить конфиденциальность пользователя. В таком сценарии имеет смысл избегать написания одной библиотеки для Android и другой для iOS. Наличие только общей библиотеки избавило бы нас от необходимости поддерживать две разные базы кода и уменьшило бы вероятность появления большего количества ошибок.

Это хорошо, но как мы можем сделать что-то подобное? Войдите в Раст. С помощью Rust вы не только сможете использовать один и тот же код на нескольких платформах, но также сможете воспользоваться преимуществом повышения производительности, которое вы получите при его использовании.

Что мы собираемся делать

Мы собираемся написать простую общую библиотеку Rust и скомпилировать ее для Android и iOS, а в качестве бонуса мы также напишем плагин Flutter, используя тот же самый код.

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

Вы также можете прочитать этот пост, заглянув в соответствующий репозиторий GitHub.

Подготовка нашего проекта

Начнем с создания папки rust-for-android-ios-flutter и создания в ней четырех папок (android, ios, flutter и rust):

После этого просто перейдите в папку rust и создайте новую библиотеку Rust с именем rustylib:

В этой библиотеке будет только одна функция, которая получит строку в качестве аргумента и вернет новую строку. По сути, просто привет, мир! . Но просто подумайте об этом как о функции, которая может работать как точка входа в более сложный процесс, полностью написанный на Rust.

Давайте установим несколько целей

Чтобы скомпилировать нашу библиотеку rustylib для Android и iOS, нам потребуется установить на нашу машину несколько целей:

Инструменты для iOS

Для iOS мы должны быть уверены, что на нашем компьютере установлен Xcode и уже настроены инструменты сборки Xcode.

Как видите, мы также установили cargo-lipo и cbindgen.

Инструменты для Android

Для Android мы должны быть уверены, что правильно настроили переменную среды $ANDROID_HOME. В macOS это обычно значение ~/Library/Android/sdk .

Также рекомендуется установить Android Studio и NDK. После того, как вы все установили, убедитесь, что переменная окружения $NDK_HOME установлена ​​правильно. В macOS это обычно должно быть установлено на ~/Library/Android/sdk/ndk-bundle .

Наконец, мы собираемся установить cargo-ndk, который занимается поиском правильных компоновщиков и преобразованием троек, используемых в мире Rust, в тройки, используемые в мире Android:

Настройка библиотеки Rust

Следующим шагом является изменение Cargo.toml . Просто убедитесь, что он выглядит примерно так:

Проект для iOS

Теперь давайте создадим проект iOS с помощью Xcode.

 iOS-проект

В iOS вы можете использовать 2 различных типа пользовательского интерфейса. Поскольку мы хотим показать, как использовать их оба, давайте создадим два разных типа проектов.

Раскадровка

В качестве пользовательского интерфейса мы выбираем Storyboard и называем проект rusty-ios-classic .

 iOS-проект

Сохраните его в ранее созданной папке ios.

SwiftUI

Давайте создадим новый проект iOS. Но на этот раз мы выберем SwiftUI в качестве пользовательского интерфейса и назовем его rusty-ios .

 iOS-проект

Снова сохраните его в папке ios.

Ваше дерево должно выглядеть примерно так:

iOS treeview

Пишем наш первый код на Rust

Теперь перейдите в проект Rust, откройте файл lib.rs и убедитесь, что он выглядит именно так:

Обратите внимание, что мы используем extern "C" . Это сообщает компилятору, что эта функция будет вызываться извне Rust, и гарантирует, что она скомпилирована с использованием соглашений о вызовах C.

Вам может быть интересно, зачем нам нужна эта функция hello_release. Ключевым моментом здесь является рассмотрение функции приветствия. Использование CString и возврат необработанного представления сохраняет строку в памяти и предотвращает ее освобождение в конце функции. Если бы память была освобождена, указатель, возвращенный вызывающей стороне, теперь указывал бы на пустую память или на что-то совершенно другое.

Чтобы избежать утечки памяти, поскольку теперь у нас есть строка, которая остается после завершения выполнения функции, мы должны предоставить функцию hello_release, которая принимает указатель на строку C и освобождает эту память. Очень важно не забыть вызвать эту функцию из кода iOS, если не хотим нарваться на неприятности. Если вы внимательно посмотрите на эту функцию, то заметите, что она использует способ управления памятью в Rust, используя область действия функции для освобождения указателя.

Этот код мы будем использовать в наших проектах для iOS.

Компиляция для iOS

Прежде чем мы скомпилируем библиотеку для iOS, мы сгенерируем заголовок C, который будет работать как мост для нашего кода Swift, чтобы он мог вызывать наш код Rust.

Для этого мы будем использовать cbindgen:

Это должно создать файл с именем rustylib.h, содержащий следующий код:

Обратите внимание, что cbindgen автоматически сгенерировал для нас интерфейс C очень удобным способом.

Теперь давайте скомпилируем нашу библиотеку Rust, чтобы ее можно было использовать в любом проекте iOS:

Проверьте папку target/universal/release и найдите файл с именем librustylib.a . Это двоичный файл, который мы собираемся использовать в наших проектах для iOS.

Использование двоичного файла iOS

Сначала мы скопируем наши файлы librustylib.a и rustylib.h в папку ios:

Вы должны увидеть древовидную структуру, подобную этой, с включением и файлом libs:

 Копировать файлы iOS

Как вы понимаете, делать это вручную каждый раз, когда вам нужно скомпилировать новую версию вашей библиотеки Rust, было бы очень утомительно. К счастью, вы можете автоматизировать этот процесс с помощью простого сценария bash, подобного этому.

Теперь вам нужно будет сделать следующее только один раз (дважды, если вы создали два проекта iOS, как описано в статье).

Давайте откроем наш проект rusty-ios-classic в Xcode и сделаем следующее:

Добавьте файл librustylib.a в раздел Общие > Платформы, библиотеки и встроенный контент. Убедитесь, что вы видите там имя библиотеки. Если он не отображается, попробуйте еще раз. Я не уверен, является ли это ошибкой Xcode, но в большинстве случаев вам нужно будет добавить его дважды, чтобы он работал правильно.

Добавить библиотеку

После этого перейдите на вкладку Настройки сборки, найдите пути поиска и добавьте пути поиска заголовка и библиотеки. Вы можете использовать относительные пути или использовать переменную $(PROJECT_DIR), чтобы избежать жесткого кодирования вашего локального пути.

 Добавить пути поиска заголовков и библиотек

Наконец, давайте добавим заголовок Objective-C Bridging . Найдите связующий заголовок на вкладке Настройки сборки:

Повторите то же самое для нашего проекта rusty-ios, если вы хотите попробовать оба типа проектов iOS.

В нашем проекте rusty-ios

Если вы используете проект, использующий SwiftUI в качестве пользовательского интерфейса, откройте файл ContentView.swift и придайте ему следующий вид:

Запустите проект в Xcode.

В этом случае вы должны увидеть Hello from Rust: Rob в эмуляторе или устройстве, которое вы используете для тестирования приложения.

Показать iOS результат

В нашем проекте rusty-ios-classic

Если вы используете проект с пользовательским интерфейсом Storyboard, откройте файл ViewController.swift и придайте ему следующий вид:

Запустите проект в Xcode.

Если все в порядке, вы должны увидеть Hello from Rust: Rob в панели вывода.

 Показать классический результат iOS

Проект Android

Давайте откроем Android Studio и создадим наш проект Android: Файл > Создать. > Новый проект > Основное действие .

 Создать проект Android

Назовите его rusty-android и задайте имя пакета. Мы выберем Kotlin в качестве языка по умолчанию и минимального API 22 .

 Создать проект Android

У вас должно получиться древовидное представление, подобное этому:

Android treeview

Если вы помните, когда мы обсуждали, как создать наш проект iOS, нам нужно было создать заголовок C, работающий как мост. В Android мы будем использовать Java Native Interface или для краткости JNI, и мы будем предоставлять через него наши функции. Способ, которым JNI создает имя вызываемой функции, следует определенному соглашению: Java_ _ _ . В нашем случае это будет Java_com_robertohuertas_rusty_1android_MainActivity_hello (обратите внимание, что _1 представляет символы подчеркивания _ в полном имени класса).

Как вы можете себе представить, если нам нужно назвать наши функции таким специфическим образом, это может создать проблему, если мы захотим повторно использовать тот же самый код в других приложениях Android. Однако у нас есть несколько альтернатив. Мы можем использовать какой-то прокси-класс, который следует тому же конкретному домену и названию класса, и включать его в каждый проект, или мы можем создать библиотеку Android и использовать ее везде.

В нашем случае мы собираемся создать библиотеку Android.

Создание библиотеки Android

В Android Studio выберите «Файл» > «Создать» > «Новый модуль». . Затем выберите «Библиотека Android» .

 Создание библиотеки Android

 Создание библиотеки Android

Панель вашего проекта Android Studio должна выглядеть так, как показано ниже:

 Создание библиотеки Android

Добавление немного Rust

Хорошо, давайте создадим наши функции Android, используя соглашения об именах JNI.

Перейдем в папку rust/src и создадим новый файл android.rs:

Получив его, скопируйте в него этот код:

Подождите, что здесь происходит?

Нам лучше ненадолго остановиться и немного объяснить предыдущий код.

Во-первых, в верхней части файла мы видим две разные директивы:

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

Хорошо, но тогда почему вы создали две разные функции ( helloDirect и hello ), а не одну?

Ответ заключается в том, что я хотел показать вам два способа работы с частью Android и позволить вам решить, какой из них более удобен для вашего проекта.

Первая функция использует крейт jni без взаимодействия с кодом lib.rs (также известным как код iOS), а вторая использует тот же код, что и в файле lib.rs.

Разница очевидна.Первая функция намного понятнее и лаконичнее второй. Кроме того, во втором нам приходится иметь дело с функцией hello_release и unsafe, а в первом — нет.

Итак, что нам делать? На мой взгляд, я бы использовал первый. Это очень простой пример, когда мы просто создаем строку и возвращаем ее. В идеале эта логика также должна быть инкапсулирована в чистую библиотеку Rust, которая будет использоваться как кодом iOS, так и Android. Эти фрагменты кода должны быть связаны только с обеспечением связи с iOS и Android через заголовки C и JNI, вот и все. Так что в идеале в нашем примере вместо дублирования логики функции Java_com_robertohuertas_rusty_1android_1lib_RustyKt_helloDirect мы должны вызвать другую библиотеку.

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

Еще один важный момент. Обратите внимание, что мы экспортируем наши функции в system вместо C. Это просто для того, чтобы cbindgen не генерировал сигнатуры для этих функций Android.

Но подождите, это не сработает! Мы не раскрывали наш модуль Android.

Добавьте это в файл lib.rs:

Атрибут cfg предотвратит компиляцию только что созданного модуля Android, если мы не ориентируемся на Android.

Компиляция для Android

Давайте подготовимся к компиляции нашего кода для Android.

Создайте папку scripts внутри папки rust и добавьте файл android_build.sh со следующим содержимым:

Подобно ранее предложенному скрипту сборки для iOS, этот скрипт поможет нам скомпилировать и переместить необходимые файлы в нашу ранее созданную библиотеку Android.

Если вы выполните этот скрипт bash , после завершения процесса компиляции вы сможете найти древовидное представление, подобное этому, с недавно созданной папкой jniLibs с несколькими подпапками в ней, ссылающимися на несколько архитектур:

 Древовидная структура библиотеки Android

Написание библиотеки Android

Наконец, мы собираемся написать код нашей библиотеки Android и использовать его из нашего приложения Android.

Давайте создадим новый файл в android/rusty-android-lib/src/main/java/com/robertohuertas/rusty_android_lib с именем rusty.kt. Обратите внимание, что имя должно совпадать с тем, которое мы использовали при определении наших функций JNI в нашей библиотеке Rust.

Скопируйте в него следующий код:

Здесь мы только что объявили две сигнатуры, отражающие две наши функции Rust (помните имя, которое мы дали им в нашем коде Rust) и функцию, которая будет вызываться для динамической загрузки библиотеки. Обратите внимание, что мы используем не имя библиотеки (librustylib.so), а имя, которое мы дали контейнеру.

Сборка библиотеки Android

Если вы хотите сгенерировать файл .aar, готовый к использованию любым приложением Android, просто используйте вкладку Gradle в Android Studio и найдите задачу с именем assemble . Щелкните его правой кнопкой мыши и выберите «Выполнить». Это скомпилирует вашу библиотеку, и вы сможете найти ее по адресу android/rusty-android-lib/build/outputs/aar/rusty-android-lib-release.aar .

Использование библиотеки Android

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

В нашем примере нам просто нужно добавить библиотеку в качестве зависимости в наш файл android/app/build.gradle:

Затем в Android Studio выберите «Файл» > «Синхронизировать проект с файлами Gradle».

Теперь откройте файл content_main.xml, расположенный по адресу android/app/src/main/res/layout, и добавьте идентификатор в TextView, чтобы мы могли ссылаться на него позже и программно изменить его значение:

После этого мы собираемся использовать нашу библиотеку Android из нашего файла MainActivity.kt, расположенного по адресу android/app/src/main/java/com/robertohuertas/rust_android. Откройте его и напишите это:

Готово! Запустите его в своем эмуляторе, и вы должны увидеть в приложении текст Hello from Rust: Rob. Кроме того, если вы нажмете кнопку ниже, закусочная покажет Hello from Rust: Rob direct . Как видите, мы используем обе функции: одна вызывает функцию iOS, а другая использует только крейт jni-rs.

Приложение для Android результат

Проект Flutter

А теперь… приступим к бонусным баллам!

Поскольку у нас уже есть библиотека Android и работающий проект iOS, выполнить эту работу в проекте Flutter не должно быть очень сложно.

Основная идея состоит в том, чтобы создать пакет подключаемого модуля Flutter, чтобы при необходимости мы могли использовать наш код в нескольких проектах Flutter.

Итак, начнем!

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

В основном мы собираемся использовать наш предыдущий код для Android и iOS и использовать его в нашем проекте Flutter. Это должно быть очень просто.

Импорт библиотеки Android

Чтобы использовать библиотеку Android, которую мы создали, прежде чем использовать Android Studio. Давайте откроем проект flutter/android.

Затем, чтобы импортировать библиотеку Android, выберите «Файл» > «Создать». > Новый модуль.

 Импорт библиотеки Android

Выберите импорт пакета .JAR/.AAR:

 Импорт библиотеки Android

И используйте ранее сгенерированный путь к пакету .AAR:

 Импорт библиотеки Android

Сделав это, мы должны увидеть новую папку с именем rusty-android-lib-release folder с нашим пакетом .aar внутри вместе с некоторыми другими файлами:

Компания Google объявила, что Rust можно использовать в рамках проекта Android с открытым исходным кодом.

Крис начал свою журналистскую деятельность в 2006 году в качестве редактора Builder AU, после того как начал работать программистом на канале CBS. После пребывания в Канаде он вернулся в 2011 году в качестве редактора TechRepublic Australia, а теперь является австралийским редактором ZDNet.

Ржавчина

Стремясь уменьшить количество ошибок, связанных с безопасностью памяти, Google объявила, что версия Android с открытым исходным кодом будет поддерживать части операционной системы, которые будут построены на Rust.

Хотя приложения для Android можно писать на управляемых языках, таких как Java и Kotlin, эти языки не обладают "контролируемостью и предсказуемостью" языков более низкого уровня, таких как C и C++, используемых для создания операционной системы Android.

"Они потребляют мало ресурсов и имеют более предсказуемые характеристики производительности. В случае C и C++ за управление временем жизни памяти отвечает разработчик. К сожалению, при этом легко допустить ошибку, особенно в сложных и многопоточных кодовых базах", Команда Android написала в своем блоге.

"Rust обеспечивает гарантии безопасности памяти, используя комбинацию проверок во время компиляции для обеспечения срока жизни/владения объектами и проверок во время выполнения, чтобы гарантировать, что доступ к памяти действителен. Эта безопасность достигается при обеспечении производительности, эквивалентной C и C++."< /p>

В настоящее время в Android, если процесс, написанный на C/C++, обрабатывает ненадежные входные данные, он запускается в изолированной программной среде, которая, по словам Google, является дорогостоящей и по-прежнему позволяет злоумышленникам объединять уязвимости в системе безопасности для использования систем.

Кроме того, Google обнаружил, что половина ошибок в работе с памятью была в коде младше года, поэтому имело смысл нацеливаться на новый код Rust, а не переписывать ОС на Rust.

"Даже если бы мы перенаправили усилия каждого инженера-программиста в команде Android, переписать десятки миллионов строк кода просто невозможно", – сказали в команде.

«Сравнительная редкость старых ошибок памяти может стать неожиданностью для некоторых, но мы обнаружили, что старый код — это не то, что нам нужно срочно улучшать. Ошибки программного обеспечения обнаруживаются и исправляются с течением времени, поэтому мы ожидаем, количество ошибок в коде, который поддерживается, но активно не разрабатывается и который со временем исчезнет."

Одной из таких систем, получивших защиту от ржавчины, является Gabeldorsche, которая позиционируется как преемница Bluetooth.

Команда Android также затронула проблему обнаружения и воспроизведения ошибок памяти, чтобы иметь возможность их исправить.

"Для сложных баз кода C/C++ часто есть лишь несколько человек, способных разработать и проверить исправление, и даже при больших усилиях, затрачиваемых на исправление ошибок, иногда исправления оказываются неправильными", — написали они. .

"Обнаружение ошибок наиболее эффективно, когда ошибки относительно редки, а опасным ошибкам можно придать срочность и приоритет, которых они заслуживают. Наша способность пользоваться преимуществами улучшений в обнаружении ошибок требует, чтобы мы уделяли приоритетное внимание предотвращению появления новых ошибок. "

Одним из преимуществ использования Rust являются дополнительные ограничения и проверки, присущие языку, такие как принудительная инициализация переменных, что может предотвратить основную причину до 5% уязвимостей безопасности в Android, сообщает Google.< /p>

"Добавление нового языка на платформу Android — это масштабная задача. Существуют наборы инструментов и зависимости, которые необходимо поддерживать, тестовая инфраструктура и инструменты, которые необходимо обновлять, и разработчики, которых необходимо обучать", — заявили в команде.

"Последние 18 месяцев мы добавляли поддержку Rust в проект Android с открытым исходным кодом, и у нас есть несколько первых проектов, которыми мы поделимся в ближайшие месяцы".

Ранее в этом году Rust перешел из Mozilla в собственный фонд. Mozilla использовала Rust для создания своего браузерного движка Servo и заменила 160 000 строк C++ на 85 000 строк Rust.

Недавно Mozilla запустила ThreadSanitizer в Firefox, чтобы устранить любые гонки данных в C/C++, оставшиеся в кодовой базе браузера.

Из-за смешанной кодовой базы Mozilla была обеспокоена запутыванием рас при прохождении через код Rust, но, тем не менее, обнаружила пару чистых рас Rust.

"В целом, Rust, похоже, выполняет одну из своих первоначальных задач: позволяет нам безопасно писать больше параллельного кода", — говорится в сообщении.

"И WebRender, и Stylo очень большие и повсеместно многопоточные, но имеют минимальные проблемы с потоками. Проблемы, которые мы обнаружили, были ошибки в реализации низкоуровневых и явно небезопасных многопоточных абстракций - и эти ошибки были простыми. исправить.

"Это отличается от многих наших гонок на C++, которые часто включали случайный доступ к вещам в разных потоках с неясной семантикой, что требовало нетривиального рефакторинга кода."

Неудивительно, что Mozilla рекомендовала создавать любые новые проекты на Rust, а не на C или C++.

Читайте также: