Также конструктор автоматизирует интеграцию библиотек на Rust в компоненту на С++. Таким образом на С++ будет описана только базовая логика взаимодействия компоненты и платформы, а вся основная логика будет реализована в библиотеке на Rust. Этот подход выбран, так как реализовать native API на С++ проще, и также взаимодействовать с библиотекой на Rust через FFI интерфейс несложно, и мало отличается от обычного вызова методов из той же программы на С++.
Я думаю, общая идея понятна, перейду к примерам.
Используя конструктор, создам внешнюю компоненту и несколько методов.
Первый простой пример, для демонстрации общего принципа работы конструктора.
Добавлю функцию, которая просто будет возвращать строку из метода на rust.
Запущу конструктор (это приложение разработанное на tauri)
Окно приложения
На закладке Функции добавлю новую функцию
Укажу русский и английский синоним для функции. Параметров у нее не будет, поэтому таблица Параметры пустая. По умолчанию установлен флаг "Вызов Rust метода". В случае установки этого флага буде создан весь необходимый код для взаимодействия с Rust:
- Будут созданы заголовочные файлы с описанием сигнатур функций на Rust;
- Будет создание код на С++ который вызывает метод Rust;
- Реализовано освобождение памяти после того, как С++ код прочитает значение, которое вернут Rust (общение между С++ и Rust происходит через указатели, поэтому нужно освобождать память);
- На стороне Rust будут так же созданы соответствующие методы.
Так как добавляется функция, автоматически установлен флаг "Возвращает значение".
И нажму "Save".
Настройки готовы, теперь можно сгенерировать код.
Для этого на закладке "Сборка" нажму кнопку "Собрать".
После чего в каталоге, где расположена программа, будет создан каталог с исходным кодом компоненты "new component".
Этот каталог содержит код на С++ и Rust
Теперь нужно собрать внешнюю компоненту. Так как библиотека на Rust статическая и включается в динамическую библиотеку (внешняя компонента это технически динамическая библиотека), то сначала нужно создать библиотеку на Rust, а потом на C++.
Для этого нужно подготовить среду для сборки.
Для Rust, нужно скачать и установить приложение-установщик со страницы https://www.rust-lang.org/ru/tools/install.
Для C++ нужно скачать и установить visual studio со страницы https://visualstudio.microsoft.com/vs/community/.
Для разработки на Rust я использую две IDE, VSCode и RustRover.
Открою каждую папку в своей IDE (С++ в visual studio, Rust в RustRover).
Важно! Открывать С++ нужно через CMake файл
И выбрать файл CMakeLists.txt из папки, которая была создана при нажатии на "Собрать"
В проекте на С++ для каждой добавленной в конструкторе функции будет создан одноименный файл *.cpp
Который вызывает метод на Rust
Для моей текущей задачи в коде на С++ ничего менять и добавлять не нужно.
Перейду к кода на Rust. Отрою его в IDE RustRover.
В Rust так же для каждого метода добавленного в конструкторе будет создан одноименный файл.
Для моей текущей задачи также ничего дорабатывать в коде на Rust не нужно, так как сгенерированный код и так по умолчанию возвращает строку "returder value from rust".
Поэтому просто соберу библиотеку на Rust командой cargo build
После сборки в каталоге rust появится собранная статическая библиотека (файл с расширением lib)
Теперь нужно создать динамическую библиотеку (чем является компонента) на стороне С++
Статическая библиотека уже прописана в фале CMakeList.txt, добавлять ее не нужно. Исходные файлы так же автоматически добавятся при генерации кода конструктором.
После сборки в каталоге cpp также появится собранная библиотека, уже динамическая (файл с расширением dll)
Все готово! Можно использовать компоненту в 1С.
В созданном каталоге также есть шаблон обработки для тестирования компоненты.
Добавлю в конфигураторе вызов моего метода
И запущу в режиме предприятия.
При запуске вывелась строка, которую возвращает метод Rust.
Второй пример посложнее. Метод должен получить данные из SQLite и вернуть в виде строки (список пользователей).
Добавлю еще одни метод, назову его ПолучитьПользователей
И аналогично нажму "Собрать" на закладке "Сборка".
В С++ и Rust, аналогично первому примеру, также добавились файлы для реализации новой функции.
Для работы с библиотекой SQLite в Rust я буду использовать крейт (так в rust называются библиотеки или пакете, терминологически правильно говорить крейт) rusqlite.
Так как я собирают приложение на rust в статическую библиотеку, то все ее зависимости также должны быть включены в нее статически, включая библиотеку rusqlite.
Для этого в файле cargo.tolm в секции "Зависимости" укажу
bundle означает, что rusqlite будет включена в мою библиотеку статически.
Полный код на rust для файла impl_GetUsers.rs, который реализует метод ПолучитьПользователей(), будет такой.
Функция getUsers выполняет запрос и возвращает пользователей в виде вектора строк (вектор в rust это аналог динамического массива).
Функция main через метод join объединяет элементы вектора в строку и возвращает функции на C++, которая уже вернет его функции на встроенном языке.
Также как и в прошлом примере, соберу сначала библиотеку на Rust , а потом на С++ (полностью аналогично первому примеру).
Добавлю метод в обработку.
И выполню в режиме предприятия.
Конструктор распространяется бесплатно.